Avrdude

Avrdude1 seems to be the standard way that people program AVR microcontrollers (unless they’re using Atmel’s own software).

Obviously the first step is to find the avrdude software. You could compile it yourself, but I tend to leave that to someone else. Here are a couple of ways which work for me.

Avrdude on Linux

Debian and Ubuntu (at least) have avrdude packages so just install it. Everything’s in the right place so just run it:

$ avrdude
Usage: avrdude [options]
Options:
  -p <partno>                Required. Specify AVR device.
...

Avrdude on the Mac

These days, May 2014, avrdude is available through homebrew, so just:

$ brew install avrdude
$ avrdude
Usage: avrdude [options]
...

Avrdude in the Arduino software

A little more effort is needed here, because you have to tell the avrdude where to find its configuration file too. Suppose the root of the Arduino software is stored in $A, then:

$ $A/hardware/tools/avr/bin/avrdude \
    -C $A/hardware/tools/avr/etc/avrdude.conf

avrdude: no programmer has been specified
         on the command line or the config file
         Specify a programmer using the -c option
         and try again


Actually it seems that the Linux Arduino package doesn’t contain avrdude.

Software format

You’ll also need to a file to send to the board. Avrdude likes ihex files which you can make with objcopy in the GNU binutils software.

Talking to the Arduino bootloader

Normally the Arduino2 is programmed with a small bootloader3 which accepts the programs we write. Under the hood, the Arduino IDE calls avrdude to do the task. Happily the Arduino appears to be a STK500 programmer which avrdude’s supported for ages.

The examples below all work on the Diecimila and Duemilanove. They might work on other types of board too, but I’ve not tested them.

We’ll assume that $AVRDUDE has been set to a suitable incantation to invoke avrdude. Then to send foo.hex to the Arduino just do this:

$AVRDUDE -q -V -F -c stk500v1 -v 19200 -P /dev/cu.usb* \
   -p atmega168 -U flash:w:foo.hex

What does all this mean ?

Writing a bootloader to the Arduino

Another fairly common task is to write a bootloader to a new ATmega chip: that turns an ATmega168 chip as produced by Atmel into a chip which works in the Arduino.

The information here I cribbed from the web, inter alia:

Musing on fusing

The recipes in the articles above almost work, but there seems to be a problem with the value of the extended fuse. Happily, an article at tinker.it6 explains what’s going on.

In essence: the ATmega chip has a bunch of configuration settings called fuses which control various aspects of memory management, what sort of clock’s being used and so on. When the chip is programmed these have to be set correctly or the thing just won’t work.

Although most configuration settings need only a few bits of data, they’re arranged into three fuse bytes: low, high, and extended. On the ATmega168’s extended fuse it seems that only the three least-significant bits actually matter, and avrdude knows to mask out the value sent. However, when the fuse is read back, those masked bits are read as 0, which results in an error like this:

avrdude: safemode: lfuse reads as FF
avrdude: safemode: hfuse reads as DF
avrdude: safemode: efuse reads as 0
avrdude: safemode: efuse changed! Was f8, and is now 0
Would you like this fuse to be changed back? [y/n] n
avrdude: safemode: Fuses OK

That’s all a bit tedious! Incidentally, if you answer ‛y’ at the prompt then avrdude just hangs.

Obviously the solution is just to set the extended fuse to 0x00, which gives us this prescription:

AVRDUDE_ALL=$AVRDUDE -q -V -c stk500v2 \
   -P /dev/cu.usbmodem* -p atmega168

$AVRDUDE_ALL -e -U lock:w:0x3F:m -U hfuse:w:0xDF:m \
   -U lfuse:w:0xFF:m -U efuse:w:0x00:m
$AVRDUDE_ALL -D -U flash:w:bootloader.hex:i
$AVRDUDE_ALL -U lock:w:0xCF:m

Hardware

You’ll need some extra hardware to do this. I’ve got an Olimex AVR-ISP5007 which does the job nicely. It is a stk500v2 compatible device, and on my Mac it appears at /dev/cu.usbmodem*. So the basic incantation is straightforward:

$AVRDUDE -q -V -c stk500v2 -P /dev/cu.usbmodem* -p atmega168

Other programmers will work too. For example:

Firmware

The only other thing you’ll need is the bootloader itself. If $A points to the Arduino root directory, then you can find the file in $A/hardware/bootloaders/atmega168/ATmegaBOOT_168_diecimila.hex.

Writing software to the Arduino without a bootloader.

This is all somewhat speculative. I think that we basically follow the recipe above for writing a bootloader but upload our own hex file instead. I think that the extended fuse bits should be set to 0x01 though, so that on reset we execute from 0x0000 and not the start of the bootloader area.

If anyone can confirm or correct this, I’d be delighted.