Programming Atmega328p with Avrdude
Arduino IDE it’s an awesome tool and helps a lot of beginners take the first steps with embedded systems. When you start to have bigger projects you may want to change to another tool, my tool of choice for embedded systems is Vim and with that comes using a makefile when I want to compile my projects.
I’m doing this tutorial to explain to others how to compile your Arduino code without the IDE. This requires you to use a library called AVR Libc from Atmel, which is a C library for Atmel AVR 8-bit RISC microcontrollers. The full documentation can be found here.
Before starting the tutorial we need a set of tools that already come with the Arduino IDE. The two major tools are a compiler and software to upload our binary to the microcontroller.
Installing the tools needed in Macos is fairly easy using homebrew. We need to run the following command:
brew install avrdude avr-gcc avr-objcopy
Our code example is the LED blink and it’s like the hello world of embedded systems. Consists of an LED that blinks at a given frequency. The difference from the implementation that you may be used to is the fact that will be using the AVR Libc.
#ifndef F_CPU | |
#define F_CPU 16000000UL // cpu frequency | |
#endif | |
#include <avr/io.h> | |
#include <util/delay.h> | |
#ifndef DELAY_MS | |
#define DELAY_MS 2000 | |
#endif | |
int main(void) | |
{ | |
DDRB |= (1<<DDB5); // set led (pin 13 / PB5) on PORTB to output | |
while(1) | |
{ | |
PORTB |= (1<<PORTB5); // set pin 13 / PB5 on | |
_delay_ms(DELAY_MS); // delay ms amount | |
PORTB &= ~(1<<PORTB5); // set pin 13 / PB5 off | |
_delay_ms(DELAY_MS); // delay ms amount | |
} | |
} |
The implementation of blink.c
will turn on and off the LED 13 from your Arduino Uno every two seconds.
As I said before my tool of choice is make
. This is a build tool that will execute the compilation and conversion to our binary that late will be uploaded to the microcontroller.
The compilation of this example has three steps, shown here:
- Compile the blink.c from C code to an object
- Convert the object to an ELF file
- Convert the ELF file to a binary HEX file
Of course, as your project gets bigger the Makefile will get more complex. The use of dependencies and compatibility with different microcontrollers will make your code and build steps a new challenge. But meantime we just want to understand how to compile our simple “hello world!”.
all: | |
avr-gcc -g -Os -mmcu=atmega328p -c blink.c | |
avr-gcc -g -mmcu=atmega328p -o blink.elf blink.o | |
avr-objcopy -j .text -j .data -O ihex blink.elf blink.hex | |
clean: | |
rm *.o *.elf *.hex |
To run the Makefile
, you just need to be in the same directory as the Makefile
and run the following command:
make
Yeah, now we have our binary file to be uploaded to the microcontroller. To accomplish that, Atmel has the avrdude
.
Run the following command and parameters:
avrdude -p m328p -P /dev/tty.usbmodem1411 -c arduino -b 115200 -D -U flash:w:blink.hex:i -v
Now you should see your Arduino LED 13 switching on and off every 2 seconds.