Месечни архиви: януари 2013

linux boards

Linux GPIO programmer for AVRDUDE

Hello!

Here you’ll find a tutorial and example of how to connect an AVR microcontroller to the GPIO pins of an embedded Linux system and use avrdude with the linuxgpio programmer type to program it.

Embedded Linux systems are small computers running Linux. Usually they will have quite a bit of available GPIO (General purpose input output) pins which you can toggle between 1/0 using /sys/class/gpio interface provided by the Linux kernel. Although small Linux computers are very capable, frequently they work in cooperation with even smaller computers like the 8 bit AVR microcontrollers. That can be quite handy if you need to handle some hard realtime task for example.

Traditionally to upload new firmware to these little helpers you would use a bootloader and connect them to a spare UART for example. This presents a chicken and egg problem of programming the bootloader in the first place. Also you may want to use every bit of flash available on the micro and not spare any for a bootloader, or not have a spare UART and so on. That’s where the linuxgpio programmer described here come into play. You can connect the AVR ISP programming interface to any four spare GPIO pins (usually there are plenty) of your Linux board and program it using avrdude. This can also be of interest to you if you already have an embedded Linux board (like the popular RaspberryPi, OlinuXino and the like) and want to get started programming AVRs, but don’t have a dedicated ISP programmer.

This solution have existed as a patch for avrdude 5.10 for more than two years. Luckily embedded Linux systems got much more popular now and Richard Nauber ported the patches to the current SVN version (a task I’ve been meaning to do for quite a while). This prompted me to bring the patch up to standard and with the help and feedback of the awesome people on the avrdude-dev mailing list it’s included in the official avrdude SVN. No more patches, yay! Until a new version of avrdude is released and finds its way into distributions here’s a quick description how to build and use it yourself. I’m assuming you’re doing this on a Linux system with a complete C development environment – gcc, autotools, etc. If you get some errors try to figure out which package is missing and install it using your distributions package manager.

First, checkout a fresh copy of avrdude SVN trunk:

$svn co svn://svn.savannah.nongnu.org/avrdude/trunk

Bootstrap autotools:

$cd trunk/avrdude
$ ./bootstrap

The linuxgpio programmer is not enabled by default, because it’s usually only useful for embedded Linux systems. You have to pass an additional option to configure to enable it:

$./configure --enable-linuxgpio=yes

If you’re doing a cross-compile as opposed to a native build you may want to pass some additional options like:

$./configure --host=arm-angstrom-linux-gnueabi --enable-linuxgpio=yes

Finally:

$make

If all went well you should have the avrdude executable and avrdude.conf files in the current directory. If you want to do things the proper way you can try to prepare a package for your favourite distribution (in which case you may find it easier to sart from an available source package). I won’t bother with this for now and just copy the two files mentioned above to my board using scp.

Now, time for some hard(ware) work! You need to connect your Linux system’s GPIO pins to the AVR and also supply power to it. It’s recommended that you take some measures to keep the magic smoke in. Make sure both systems use the same or compatible voltage levels i.e. 3.3V vs 5V. It’s also a good idea to put some resistors in series to limit the maximum current. A more robust approach would be to put a 3-state buffer in between, you can find a description of such a setup here.

For my tests I made a simple straight trough cable connecting the 4 GPIO pins, 3.3V power and GND from a RaspberryPi to the ISP connector of a Freeduino board, equipped with an Atmega168. Note that this make the Atmega168 work a bit out of spec, because at 3.3V its max frequency is 12MHz and not 16MHz but it worked fine for me. Also note the Freeduino is not connected or powered by anything else, as it normally runs on 5V, only 3.3V is being supplied through the ISP connector. It happened so that I used the pins for the hardware SPI interface of the RPi, but this need not be so, they were just the most convenient to wire with 3.3v and GND on the sides.

The picture in the beginning shows my test setup with the Freeduino connected to the RaspberryPi. Next to it, showing some other Linux boards which can be used instead – OlinuXino maxi and a Bifferboard (where it all started).

Jump to your Linux board, wherever you copied avrdude and avrdude.conf and open the latter with a text editor. By default the entry of the linuxgpio programmer is commented out, because there is no way to know how you wired things up in your setup. Uncomment it and replace the question marks with the GPIO pins to match your wiring scheme. Note that in the first version of this patch the GPIO numbers were off by one (i.e. you had to put 13 in the config file if you meant GPIO 12). This has been fixed, so now you need to put the correct number. In my case:

programmer
id = "linuxgpio";
desc = "Use the Linux sysfs interface to bitbang GPIO lines";
type = "linuxgpio";
reset = 22;
sck = 10;
mosi = 11;
miso = 9;
;

The moment of truth:

root@raspberrypi:/tmp# ./avrdude -C avrdude.conf -c linuxgpio -p m168 -U flash:w:blink.hex

If you’re lucky you should see something like this:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9406
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 „blink.hex“
avrdude: input file blink.hex auto detected as Intel Hex
avrdude: writing flash (3526 bytes):

Writing | ################################################## | 100% 1.77s

avrdude: 3526 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: load data flash data from input file blink.hex:
avrdude: input file blink.hex auto detected as Intel Hex
avrdude: input file blink.hex contains 3526 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 1.97s

avrdude: verifying …
avrdude: 3526 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done. Thank you.

root@raspberrypi:/tmp#

Enjoy!