Playing with Arduino board and its graphical development environment I felt the urge to work closer to the hardware, stepping away from the default library and the Java IDE and using the compiler directly from the command line. Fortunately all the tools are there, because the Arduino IDE uses them under the hood. So I tried to use the avr-gcc compiler and the avrdude uploading tool, directly with pure C code.
To make it simple I implemented the classic blink program that toggles the output pin connected to the on-board LED. The Arduino Uno schematics indicate that the LED is connected to the PB5 pin of the Atmega328p chip, so that’s the pin I need to control. The AVR compiler is complemented with a C library: avr-libc, which contains useful functions and headers to develop for AVR chips without using assembly language. Inside the avr-libc manual and the Atmega328p datasheet there are many examples on how to toggle IOs, and with them I prepared the following code:
#include <avr/io.h>
#include <util/delay.h>
enum {
BLINK_DELAY_MS = 1000,
};
int main (void)
{
/* set pin 5 of PORTB for output*/
DDRB |= _BV(DDB5);
while(1) {
/* set pin 5 high to turn led on */
PORTB |= _BV(PORTB5);
_delay_ms(BLINK_DELAY_MS);
/* set pin 5 low to turn led off */
PORTB &= ~_BV(PORTB5);
_delay_ms(BLINK_DELAY_MS);
}
return 0;
}
The Port “B” of the microcontroller can be changed bit by bit with special instructions called “sbi” and “cbi“, and the compiler recognizes those kind of accesses generating optimized assembly in case of bit-wise operations. The ports definitions and useful macros (like “_BV“)can be found in the “/usr/lib/avr/include/avr/iom328p.h” and “/usr/lib/avr/include/avr/sfr_defs.h” headers.
In order to compile a program and upload it to the Arduino Uno, I need to create an IHEX file and use the avrdude tool to load it inside the Flash. Most of the parameters and options of the avr-gcc and the avrdude tools for the Uno board can be found in the “hardware/arduino/boards.txt” file from inside the Arduino IDE installation directory, and some other information is present in the avrdude manual. The commands that I used to compile and upload the “led.c” code above are:
$ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c $ avr-gcc -mmcu=atmega328p led.o -o led $ avr-objcopy -O ihex -R .eeprom led led.hex $ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: reading input file "led.hex" avrdude: input file led.hex auto detected as Intel Hex avrdude: writing flash (88 bytes): Writing | ################################################## | 100% 0.02s avrdude: 88 bytes of flash written avrdude: safemode: Fuses OK avrdude done. Thank you.
The code is uploaded and the led starts blinking. Well that was easy, mostly due to the fact that the tools have good support for the Arduino.
It is also possible to do a backup of the Atmega328p Flash content by using this command:
$ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:r:flash_backup.hex:i
See also:
- Can’t hack, won’t hack: Programming the Arduino in Pure C
- Johannes Hoff: Arduino on the command line
- Martin’s Atelier: Arduino from the command line
Entries
Lev Abalkin
2011/04/24
Thank you.
Please update adruino.cc with this piece of information.
Balau
2011/04/30
I added this post in Code Library and Tutorials.
Dipesh
2011/09/30
Thank you very much for this very short and effective getting started guid.
Ernesto
2011/11/29
could you post how to create/modify a code to create a switch between a small microphone with two outpust, one being speakers and the other being headphones.
Balau
2011/11/29
I haven’t played with audio yet, so I can’t really help you very much.
I think you have two ways to do it:
The first is to use electronics (amplifiers, transistors, …) to bring the signal from the mic to the speakers and the headphones, and use the Arduino only to switch on/off some transistors to make the sound go where you want to go.
In this case the code should be quite simple, you set one GPIO as an input button and two as outputs (one high one low). Then you poll the input button, and when it is pressed, you switch the logic level of the two output GPIOs.
The second is to sample the audio with the Arduino using the ADC and creating the sound with two PWM outputs that you enable/disable based on an input button connected to a GPIO. For better sound I suppose you need to raise the ADC sampling frequency by setting the prescaler to a low level; see this page: Faster Analog Read?. To output the audio, see this introduction: Play Melody
In this forum you can find people who can help you better than I can:
Using Arduino – Audio
ed
2012/01/01
Good to know. But I presume using AVRDude to ‘get it into the Flash’ means getting an AVR programmer?
Balau
2012/01/01
Actually Arduino has a built-in way to program the flash, using a chip placed between the USB and the AVR microcontroller. avrdude is able to use the “Arduino way” of uploading the code, without using a programmer.
ed
2012/01/01
I know I can use an Arduino to program an AVR micorcontroller and actually have done so already, but that is still from within the ARduino IDE, using the Arduino as a programmer.
But how to do that with a hexfile instead of a pde, using an Arduino as programmer, I would not know.
Could you expand? Would really be helpful. Which ‘chip’ betweem the USB and the AVR? is that the to be programmed chip or the chip that does the programming?
Balau
2012/01/02
If you use the Arduino IDE, go into File->Preferences, and enable verbose output during compilation and upload. It will show in the lower command window what happens under the hood. And under the hood the Arduino IDE actually uses avrdude. It transforms the pde file into a C++ source file and compiles it (using avr-gcc) with the libraries to create an ELF file, which is then converted into an hex file by avr-objcopy. The hex file is then uploaded with avrdude.
In my last comment I forgot to tell that other than the USB-to-serial chip (which is an FTDI or small AVR) there is also a bootloader inside the AVR flash that allows to program the AVR without a programmer. See also these pages:
http://arduino.cc/en/Hacking/Bootloader
http://arduino.cc/en/Tutorial/Bootloader
ed
2012/01/02
Thanks Balau. I am familiar with that, but maybe I did not pose my question clearly.
From your article I understood that you could use the Arduino IDE to upload (‘program’) a hex file to an AVR chip.
It still is not clear to me:
-I write a program in C -> that gives me a hex file. I know the exact name of that hex file even without verbose Arduino
-How to get that hexfile into the Arduino board if not with a Programmer?
-If there is a way to get that hexfile programmed into an arduino with the Arduino IDE (as yr article seems to suggest) I’d be glad to learn that.
Tnx
ed
2012/01/02
Just additional: as I said before: I know how to program an AVR chip with an arduino, but then I use a pde file (yes, under the hood that is converted to hex and then uploaded with avrdude)
But if you only have the c generated hexfile, so not a .pde or .ino file, but a hexfile, developed in a C compiler. How to get that into a chip with the arduino?
Balau
2012/01/02
OK sorry if I don’t understand, you know, new year’s eve…
So your objective is to upload an HEX file into an AVR chip, using an Arduino as the programmer.
I never did it, but I don’t think it can be done in the IDE, because the “workflow” is quite fixed, or at least I don’t know how to do it. Instead I think it can be done with avrdude. To upload an HEX file into an AVR chip, you can use an Arduino as an ISP with this sketch that emulates an avrisp programmer:
https://github.com/rsbohn/arduinoisp
You upload it on the Arduino with the IDE, but be aware that it does not work on all Arduinos (Uno is excluded for example)
Then when the program is uploaded, you connect the chip in a way similar to that explained here:
http://arduino.cc/en/Tutorial/ArduinoISP
Then the way to use Arduino as ISP with avrdude is presented here:
http://code.google.com/p/mega-isp/wiki/AvrispArduino
The complete command should be something like this:
avrdude -F -V -c avrisp -p ATMEGA328P -P /dev/ttyACM0 -b 19200 -U flash:w:myprogram.hexIf you substitute myprogram.hex with your HEX file, ATMEGA328P with the AVR chip you want to program, “
/dev/ttyACM0” with the serial port on which is connected the Arduino, it should work.ed
2012/01/02
Thanks,
I know how to use the IDE+Arduino as an AVR programmer (and have done so many times), but that only works for IDE developed programs
, not (to my knowledge) for externally developed Hex files.
I don’t think it can be done either and that is why I asked, coz it is what your article seemed to suggest
The method you describe now, is however an interesting one and it may well work, provided one first loads the ‘Arduino as ISP programmer’ sketch (otherwise one might reprogram the arduino chip.
I am gonna give that a try
Balau
2012/01/02
In my article above I show that it is possible to upload an HEX file on an Arduino board that still has the bootloader in flash, using avrdude and no programmers, and my objective was to avoid the IDE and Arduino libraries completely. I am sorry if I unintentionally misled you.
Good luck!
ed
2012/01/02
Balau, no apologies necessary. That was sort of what I thought you were doing, But I thought you were trying to get a hexfile in an empty chip, without a programmer.
Sorry for the confusion, but thanks for the info
Phil
2012/01/04
Balau,
Is it possible to program the ATmega328 in assembly rather than C?
Balau
2012/01/05
Absolutely. The “
avr-as” program can be used to compile assembly files.If you run compilation of my example with “
avr-gcc -save-temps -DF_CPU=16000000UL -mmcu=atmega328p -Os -c -o led.o led.c” then it will create “led.s” that contains an example on how to write a main in assembler.One thing to take into account with respect to C programming is that you might want to override the “crt” library, which contains the boot code and the interrupt vectors. If you add “-nostartfiles” to the linking command, it will not link the “crt” library included in the toolchain. I am assuming that if you want to program an AVR in assembler, you know what you are doing.
Phil
2012/01/11
Thanks for you reply Balau! I’m actually relatively inexperienced with assembly but wanted to learn avr’s assembly language rather than x86 assembly so forgive my lack of knowledge. So once I have an object file generated by avr-as I can use avrdude to write that object file to flash on my microcontroller?
Balau
2012/01/12
From the assembly file you create an object file (“.o”), then you use avr-gcc as a linker to create the “executable” file, and then from the executable you can create an hexadecimal file with avr-objcopy. The hexadecimal file can be uploaded with avrdude.
avr-as can be called directly, or it can be called implicitly if you use avr-gcc to compile the assembly file.
See this guide, especially chapter 11:
http://www.network-theory.co.uk/docs/gccintro/
Most of the things you can find anywhere for GCC can be applied to avr-gcc and the AVR toolchain.