I recently got an Arduino UNO as an alternative to using plain atmel microchips with troublesome circuitry. I've been able to easily program the Arduino without using the IDE by following this post: Programming Arduino Uno in pure C | Freedom Embedded
However, I would like to find a way to program the Arduino with assembler. I've only seen posts about AVR-Studio assembler programming in Windows, using in-line assembly, and modifying the Arduino IDE, none of which I want to do. Is there a simple way of merely creating a HEX file with assembler and downloading it into an Arduino UNO via AVR-dude? If there is, how is it achieved and what tools would I require?
I'm currently using Linux(Ubuntu 12.04).
The avr-gcc toolchain will assemble assembly language source files. After all when avr-gcc compiles a c++ file it first generates an assembly language file. Which it then passes to avr-as to assemble into an object file. Which is then passed to avr-ld to produce an executable. The toolchain comes with the Arduino IDE, or you can get it from the Ubuntu repositories.
hehe it looks like you are not very keen on assembler?
I have never attempted assembler, is it still used now a days? You talk about speed, when would someone code in assembler as a general practice?
I've written more assembler than I care to remember, for example a Pascal compiler written in assembler for the Apple 2:
However these days it is only really required for low-level system programming, where you either need to do something not supported by other languages (eg. C) or something very timing-specific.
Modern C (and C++) compilers optimize very well. You will probably write slower code if you try to do it yourself in assembler, unless you are a real expert. The compiler can keep track of register usage, use "tricks" you may not have thought of, move instructions around, and generally produce fast, tight code.
It's fine to learn how to read it, knowledge is always useful. But I wouldn't be writing a big project in assembler these days, personally.
Thanks Nick, that was a very usefull answer to my question. I had always want to have this key points clear. As you say, knowledge is always useful, and I will indeed try to learn a bit about reading the code, but now I have things much more clear about how useful or not it can be for me.
@Nick: My company produced a C compiler back in the old MSDOS days. Byte Magazine was always running benchmark tests to see which compiler was the "best". One test that got most of the attention was the Sieve of Eratosthense. I remember one company consistently won that test, but was almost dead last in all of the other benchmarks. It was later discovered that the company actually built into their parser a detection for the Sieve source code and dumped out an EXE that was hand-tweaked assembler! Subsequent test revealed that most compiler vendors supplied libraries that were also tweaked assembler. While there's nothing wrong with this, the Byte benchmarks were a poor test of a compiler's code generation. Later, Computer Language published the Dhampstone Benchmark that was designed to test a compiler's code generation, rather than its library routines.
Personally, I wish I hadn't let my assembler abilities get rusty as it can still be useful. However, I would not want to code in assembler on a day-to-day basis.
econjack: @Nick: My company produced a C compiler back in the old MSDOS days. Byte Magazine was always running benchmark tests to see which compiler was the "best". One test that got most of the attention was the Sieve of Eratosthense. I remember one company consistently won that test, but was almost dead last in all of the other benchmarks. It was later discovered that the company actually built into their parser a detection for the Sieve source code and dumped out an EXE that was hand-tweaked assembler!
That's funny! In the day when I produced that compiler I remember that Sieve test, and recall that I did tweak the compiler slightly to improve its performance. Not cheating, but subtle things, like the order in which keywords were tested for in the lexer. For example, if you use "for" more frequently than "return" then if you put "for" higher up the list of keywords to be found, it will parse it slightly faster. Of course that affected compile speed, not run-time speed, but I think you could do similar things for the run-time part. A trade-off to make some things slightly faster at the expense of others. My changes however would improve compile and run-time speed for all "typical" programs, not just the Sieve one.
There is a little bit of house keeping in the actual asm file. Set up the interrupt vectors, initialize the stack, disable the watchdog timer... but once you have done it once, the template is there and using it for other programs is simply a cut and paste.
Thank you all for the quick and informative replies!
I'm doing it for educational purposes. I don't get much satisfaction out of seeing my C programs work, let alone see an Arduino Sketch work.
tf68:
The avr-gcc toolchain will assemble assembly language source files. After all when avr-gcc compiles a c++ file it first generates an assembly language file. Which it then passes to avr-as to assemble into an object file. Which is then passed to avr-ld to produce an executable. The toolchain comes with the Arduino IDE, or you can get it from the Ubuntu repositories.
terry
I searched for a way to just skip to the assembler part of the compilation, turns out avr-gcc can accept .S assembler files directly. Seems like quite a simple solution for the small amount of support available in the web. I found this out in this site: avr-libc: avr-libc and assembler programs
I haven't gotten the Arduino Uno to respond though...
TanHadron:
I use tavrasm. Here is the syntax I use in my build shell script:
There is a little bit of house keeping in the actual asm file. Set up the interrupt vectors, initialize the stack, disable the watchdog timer... but once you have done it once, the template is there and using it for other programs is simply a cut and paste.
How do I know the type of "housekeeping" I need to get it up and running?
I assume that it's either the fact that I haven't done any "housekeeping" in my code, or the shell script that's holding my code back. I'm using the same terminal commands used in Programming Arduino Uno in pure C | Freedom Embedded , maybe they were just made for C?
I would go further as to post my assembler code here to troubleshoot, but I'm afraid I may be going a bit off-topic now for an "arduino programming questions" sub-forums primarily focused on Sketches.
econjack:
Personally, I wish I hadn't let my assembler abilities get rusty as it can still be useful. However, I would not want to code in assembler on a day-to-day basis.
Agreed. I wrote a program in assembler for the Sinclair Spectrum. It was the only way to do what I wanted. If I made an error...CRASH...with no error codes or reports and the time taken to write a simple routine could be quite long. I'm happier, these days, writing in a higher level language, such as C++, where the code can be written and checked fairly quickly. I'm sure that too much assembler 'does your brain in'.
That's not to say that I regret learning assembler, as that knowledge has made higher level languages easier to understand.
Do you want to use the Arduino core? If so, it does all the house keeping for you. If you want it to be in control and call your assembly code, all you have to do is put your .S file into the build directory, and it will link it in. Then you call your assembly routines from setup() or loop().
If you want to bypass all the Arduino core and take control from the beginning, you have to deal with all the house keeping tasks. You also don't have access to standard Arduino routines. If you want timers, you have to configure them and handle the interrupts yourself. You can't do such things as analogWrite() or Serial.write(). And you don't have setup() and loop().
I'm not really sure how you would program the microcontroller while it's in the Arduino to do that, though. I always use a separate microcontroller and bypass the boot loader when I do straight assembly programs. If I didn't have another microcontroller, I wouldn't trust my assembly skillz not to brick my Arduino. And since I have another microcontroller, why not wire it up to run standalone? So I use my Arduino as an ISP and use it to program my standalone microcontroller. For test programs like blinky LEDs and such, I don't use any other external circuitry except power and ground. I turn on the internal pull-up on the reset pin, and use the internal clock so I don't need a crystal, and I disable the watchdog unless I'm using it as a sleep waker.
In my early days of programming I was told to write some modules and to do it assembler as they needed to be very efficient. Not knowing the assembler I wrote some high level code to see what the compiler would produce with the intent of then tweeking it by hand. What I found was that what the compiler generated was hard to beat. Furthemore by restructuring my high level code I found I could get the compiler to produce output that was either faster or used less memory.
The end result was that the modules were written in the high level language much simplifying support issues.
Whilst assembler can be interesting there are not a lot of cases where it is really needed.
Ironically, I use my knowledge of assembler these days largely to prove that you don't need to use it. Most times when someone says they will use assembler to "make it faster" I can prove that the code generated by the C compiler is superior, or at least, could not be beaten.
For example if someone wants to set a bit "quickly" and proposes to use assembler, I do it in C and show that the generated code does it in one or two clock cycles, which cannot be improved on.
I'm using C for all of my projects, but my curiosity doesn't allow me to not want to learn assembler. Either way, I got everything working now. I used -save-temps in the terminal when compiling simple C files and checked the .s files to see how the assembler worked. Turns out I only needed to make a few minor adjustments to the programs I previously tried to make.
Thanks to everyone who participated in this thread, you've all been very informative!