Programming atmega on arduino board
Why not arduino?
AVR atmega chips are pretty nice. What if you're feeling a bit handicaped by arduino simplicity? What if you want to do something more advanced?
Program arduino board without using arduino IDE and language (who likes this setup, loop anyway?).
Programming boards in C in Vim is much more fun it also much more low level and you'll learn much more if you try to implement your own libraries to talk with your compontents than just using already build libraries from the net which are often of rather poor quality.
If something doesn't work, it will be just your fault, not anyone else's.
Of course, this approach doesn't scale well, but learning and side projects aren't for scaling, but for trying out new things, gathering insight, and creating cool stuff.
Setup
I will assume that you have an arduino board with loaded bootloader and that you know how arduino GPIO maps to GPIO on atmega board.
Further examples will be on atmega32u4 chip.
create a directory for a project
$ cd Projects
$ mkdir atmega32u4_tutorial && cd atmega32u4_tutorial
Hello world for atmega
write a atmega hello world program like this or like below:
#include <avr/io.h>
#include <util/delay.h>
// define what pins the LEDs are connected to.
#define LED PD6
int main(void) {
// initialize the direction of PORTD #6 to be an output
DDRD |= (1 << LED);
while (1) {
// wait
_delay_ms(200);
// change value of LED pin
PORTD ^= (1 << LED);
}
}
Dependencies
Make sure that you have all dependencies installed to compile and flash your code.
On Linux it is necessary to install the packages required manually, however the effort involved is no that much different. Go to your Package Manager and install the following;
- gcc-avr
- binutils-avr
- gdb-avr
- avr-libc
- avrdude
on ubuntu:
# apt-get install gcc-avr binutils-avr gdb-avr avr-libc avrdude
Let's build it!
Now, as we have already written our hello world code and installed all needed dependencies, it would be nice to compile it.
It's usually done with make
command. If you haven't heard about make
before, grab
a make tutorial.
In short, you have to write a Makefile, which is just an ordinary file with
specifications of make commands, if you have well written Makefile
, building your
code is as simple as typying make
into a terminal.
Here is an example of a makefile:
###############################################################################
# Makefile for the project atmega32u4_tutorial
###############################################################################
## General Flags
PROJECT = atmega32u4_tutorial
MCU = atmega32u4
TARGET = atmega32u4_tutorial.elf
CC = avr-gcc
## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)
## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2 -O0 -D F_CPU=16000000
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d
## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=
## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom
HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0
## Objects that must be built in order to link
OBJECTS = main.o
## Objects explicitly added by the user
LINKONLYOBJECTS =
## Build
all: $(TARGET) atmega32u4_tutorial.hex atmega32u4_tutorial.eep size
## Compile
main.o: ../main.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<
##Link
$(TARGET): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)
%.hex: $(TARGET)
avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
%.eep: $(TARGET)
avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@
%.lss: $(TARGET)
avr-objdump -h -S $< > $@
size: ${TARGET}
@echo
@avr-size -C --mcu=${MCU} ${TARGET}
## Clean target
.PHONY: clean
clean:
-rm -rf $(OBJECTS) atmega32u4_tutorial.elf dep/* \
atmega32u4_tutorial.hex atmega32u4_tutorial.eep
## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
This Makefile
offers two commands:
make
(will compile everything)make clean
(will purge all compiled files)
Uploading our code
Ok, but what do we do with this compiled C code? It won't run on our precious computer...
Connect your arduino board with atmega32u4 to your computer. It good to know which linux device it's using.
You can look for it in /dev/
or run dmesg | tail
and look for a message about new
USB device.
To upload compiled code to your board, we will use avrdude
. It was one of dependencies
you installed before.
avrdude
has lots of options and to make my life easier I wrote a simple
script for uploading. Let's call it 'upload.sh':
#!/bin/bash
/usr/share/arduino/hardware/tools/avrdude \
-C/usr/share/arduino/hardware/tools/avrdude.conf \
-v -v -v -v -patmega32u4 -cavr109 -P/dev/ttyACM0 \
-b57600 -D -Uflash:w:atmega32u4_tutorial.hex:i
When you give it good permissions you can run it to upload compiled code to your board.
Code assumes that your arduino device on linux is called /dev/ttyACM0
, if it's called
differently you have to change your script.
$ chmod u+x upload.sh
$ ./upload.sh
If everything works fine, you should see lots of numbers on you screen (uploaded bytecode) and your atmega32u4 board should start blinking!
Congratulations!
If you learning from tweaking some example projects, take a look at, my github repository of simmilar but a bit more advanced project robocar.