One of my primary objectives once I got my head around how to write code for my Uno using the Arduino IDE was to make this more releveant to my aim of re-learning C. Arduino IDE provides a layer of abstraction and avoids some of the boilerplate. But, unfortunately it‘s not real, pure C. There are a number of comprehensive guides as to how to go about programming an Arduino using pure C, GNU Make and AVR tools. I don‘t know much about any of the tools being used so best to follow the links and read up on them.
- Programming Arduino Uno in pure C (canthack.org)
- Programming Arduino Uno in pure C (balau82.wordpress.com)
- Setting up Xcode to Compile & Upload to an Arduino ATMega328 (www.quietless.com)
That last link has an XCode template linked to it, which sounded appealing to me, initially. However the Makefile did not work for me with my Uno. In fact, none of the pages linked had Makefiles that would work for me. For a good couple of hours it was very confusing while I trialled — and mostly errored — my way around my Makefile, trying to figure out what values and configurations were right for the Uno.
Many of the tutorials advocated downloading and installing AVR programming tools such as avr-gcc, avrdude etc. This was not as straight forward on my MacBook Pro as I had hoped (i.e. there was no Homebrew package that contained them all). So I elected to use the AVR tools I found inside the Arduino IDE application.
Below is the Makefile that finally worked for me. Likely variables for other users are ARDUINO_HOME and PORT. The one value that had me stumped for ages was the BAUD value. When wrong, the RX LED on the Uno would light up briefly but the program would not be uploaded and the error message avrdude: stk500_recv(): programmer is not responding would be displayed. Many others more familiar with this sort of thing would have spotted this earlier, I‘m sure.
A working Makefile for Arduino Uno using AVR tools on Mac OS X.
This is for the Blink example.
CC=$(ARDUINO_HOME)bin/avr-gcc
CFLAGS=-Wall -Os -DF_CPU=$(F_CPU) -mmcu=$(MCU)
MCU=atmega168
F_CPU=16000000UL
OBJCOPY=$(ARDUINO_HOME)bin/avr-objcopy
BIN_FORMAT=ihex
PORT=/dev/tty.usbmodemfd131
BAUD=115200
PROTOCOL=stk500v1
PART=$(MCU)
AVRDUDE=$(ARDUINO_HOME)bin/avrdude -C $(ARDUINO_HOME)etc/avrdude.conf -F -V
RM=rm -f
.PHONY: all
all: blink.hex
blink.hex: blink.elf
blink.elf: blink.s
blink.s: blink.c
.PHONY: clean
clean:
$(RM) blink.elf blink.hex blink.s
.PHONY: upload
upload: blink.hex
$(AVRDUDE) -c $(PROTOCOL) -p $(PART) -P $(PORT) -b $(BAUD) -U flash:w:$<
%.elf: %.s ; $(CC) $(CFLAGS) -s -o $@ $<
%.s: %.c ; $(CC) $(CFLAGS) -S -o $@ $<
%.hex: %.elf ; $(OBJCOPY) -O $(BIN_FORMAT) -R .eeprom $< $@
First published on Oct 22, 2011. Last updated on: Oct 22, 2011.