To program AVR microcontrollers using the AVR Programmer for Raspberry Pi board there are several things you will need. They are:
- A Raspberry Pi (naturally)
- An assembled AVR Programmer for Raspberry Pi board
- An AVR cross-compiler toolchain (optional)
- The avrdude program (built May 26, 2013, or later) that includes linuxspi support
- The avrdude_gui front-end GUI for avrdude (optional)
- An AVR microcontroller you want to program
Configure the Raspberry Pi
I use the Raspbian distribution of Linux on my Raspberry Pi. In Raspbian the kernel driver for the SPI interface is disabled by default. The SPI driver must be enabled before you can use it to program AVR microcontrollers.
To enable the SPI interface you must remove the blacklisting entry for spi-bcm2708 in the /etc/modprobe.d/raspi-blacklist.conf file, or use the raspi-config to enable the SPI interface.
Once you have removed the blacklisting of the SPI driver you must either reboot the Raspberry Pi or load the driver manually with:
$ sudo modprobe spi-bcm2708
Install an AVR cross-compiler (optional)
If you are going to use the Raspberry Pi to write and compile programs in C for AVR microcontrollers you will need to install a cross-compiler. Install the following packages to compile programs for use on an AVR microcontroller:
- gcc-avr - The GNU C cross-compiler for AVR
- binutils-avr - Binary utilities supporting Atmel's AVR targets
- avr-libc - Standard C library for Atmel AVR development
Install the AVR programming software
- Download and install the avrdude program
- Download and install the avrdude_gui program (optional)
- Download and install wxWidgets (needed by avrdude_gui)
The avrdude_gui is optional but it makes it a lot easier to deal with all the command line switches accepted by the avrdude program. You will need my 0.5 (or later) version of avrdude_gui and not the original 0.2 version.
NOTE: The original version of avrdude_gui was writen in C++. I don't write programs in C++ so I rewrote avrdude_gui in Python and used wxWidgets for the GUI. In the process of rewriting the program I updated it to handle all of the features and options in avrdude that have been added since the original C++ based program was created. I assigned a version number of 0.5 to my Python version to distinguish it from the C++ based 0.2 version.
I will add a link to my updated Python based version of avrdude_gui later.
Assemble the interface board
Please read the following assembly instructions carefully before you start soldering components to the PCB. Not all components are on the top side of the PCB.
To build and use the interface board you will need the items listed in the components list (above). I will assume you know how to use a soldering iron, or know someone who does.
To assemble the board, I suggest adding the components in the following order:
1. All resistors
2. The DIP socket (suggested), or the 74LVC245
3. All capacitors
4. All headers EXCEPT the 2x13 pin header.
5. Install the 2x13 female header on the BOTTOM side of the board.
You may install either a 20-pin socket or the 74LVC245 on the board. I suggest using the socket as it will make it easy to replace the 74LVC245 should it ever be damaged by static or by an error in the circuit containing the AVR microcontroller to be programmed.
NOTE: Resistors R2 through R5 are optional. They are recommended to protect the 74LVC245 and the Raspberry Pi. The resistor values are suggestions and should be a good starting point. You can adjust the values as required based on the external circuitry you have around the AVR microcontroller being programmed. If you choose to omit any of the R2 through R5 resistors you will need to install a jumper in the place of the omitted resistor.
Connect the programmer to the Raspberry Pi
The programmer interface board plugs on to the GPIO header of a Raspberry Pi. When it is properly connected to the Pi the interface board will be positioned so it is completely over the Raspberry Pi.
Orient the Raspberry Pi with the USB and network connectors to the right and the GPIO header in to the left on the side of the board opposite side of the board from you. Orient the interface board with the 6-pin and 10-pin connectors to the right. Before you push the interface board down on to the GPIO header of the Raspberry Pi check that the headers are properly lined up. If the headers are offset by a pin or two you could risk damaging the Pi when you apply power.
The interface board was originally designed for use with the earlier models of Raspberry Pi which have 26-pin GPIO headers. If you are using a newer model (such as an A+, B+, or 2B) that uses a 40-pin GPIO header the interface board will be connected to the first 26-pins (the ones furthest away from the USB and network connectors) of the 40-pin header.
Connecting to an external circuit
The interface board can be connected to an external circuit containing an AVR microcontroller to be programmed by attaching a cable to either the P2 (10-pin) or P3 (6-pin) headers.
The P2 and P3 headers are using common pinouts so you can use any 6-pin or 10-pin cable you already have to connect to a programming header for an AVR microcontroller on an external board. If you are using a (solderless) breadboard without a dedicated programming header you can look at the interface board schematic to work out how to run jumper wires from either the P2 or P3 headers to the breadboard.
Supplying power to an external circuit
Header P1 can be jumpered to provide +5V to an external circuit via a cable attached to either P2 or P3. The amount of current available to an external circuit will vary based on which version of Raspberry Pi is being used and the maximum current that can be supplied by the supply powering the Pi.
If the AVR microcontroller being programmed is part of an external circuit or board that may draw a lot of current you should power the external circuitry using a separate power supply. If the external circuitry is little more than just the AVR microcontroller the interface board can be used to power by installing a jumper on P1.
NOTE: Do not power the external circuit with a separate power supply at the same time that you have a jumper in place on P1 or you may seriously damage the Raspberry Pi.
Using avrdude to program AVR microcontrollers
At this point you should have installed the required software, configured the Raspberry Pi, assembled the PCB, connected the PCB to a circuit with an AVR to be programmed, and have a binary file to be programmed in to an AVR microcontroller. This is where the avrdude program comes in to play.
If you type "avrdude -h" or "man avrdude" you will discover that the program has a lot of command line options. The updated version of avrdude_gui will make it easier to determine which options you need pass to the program for a particular task. It is beyond the scope of this project to go in to much detail about using avrdude in these instructions. Instead, just four parameters will be covered as they will be at the heart of any operation you will perform with avrdude. The four parameters are: -p -c -P, and -b.
The -p option is used to specify which AVR microcontroller is to be programmed. For example "-p ATtiny45" or "ATmega16". The -c option specifies the type of programmer being used. This project uses the SPI interface of a Raspberry Pi so you will use "-c linuxspi". The -P option specifies which port (or device, in Linux terms) will be used to communicate with the AVR microcontroller via the programmer. The device name for the SPI interface used with this project is "spidev0.0". On the command line you will need to specify the full path to the device so you will use "-P /dev/spidev0.0". Don't forget the "/dev/" part when using the command line. If you are using avrdude_gui you only need to select "spidev0.0" as avrdude_gui will automatically prepend "/dev/" when it builds the command line.
The -b option specifies the baudrate. The default value is 400000 when the -b option is not used. Whether you need to specify a value or not will depend on two factors: the clock rate of the AVR microcontroller, and the voltage powering the AVR microcontroller. When using avrdude_gui the baudrate value can be entered by first clicking within the field below the -b label. You can omit -b and use the default value when you are powering the microcontroller with 5 volts and it is being clocked at 8MHz or more.
The specific value to use for -b when the microcontroller is being operated at a slower clock rate or with a lower operating voltage will vary and may require some experimentation but it will be less than 400000. If the baudrate is too high the avrdude program will not be able to properly communicate with the microcontroller.
To test communication with the microcontroller add "-U signature:r:fuse-sig:i" to the command line to test reading of the signature bytes. If you get an error reading the signature bytes, or don't get a consistent result, lower the baudrate until you are reliably reading the signature bytes.
If the microcontroller voltage is operated at 8MHz but at 3.3V the baudrate may need to be lowered to 100000 or less. If the clock rate is lowered to 1MHz the baudrate may need to lowered considerably to 25000 or less. The lower the baudrate the longer it will take to program a microcontroller. Don't worry about using a lower value for the baudrate than you might be able to use. It is better to use a lower baudrate value and have reliable communications than trying to use the highest value possible at the risk of unreliable communications with the microcontroller.
SIDE NOTE: I have been using the SPI interface of a Pi to program an AVR microcontroller for about a year. I have found that avrdude is not always able to talk with the microcontroller. There are times I have to run avrdude multiple times to get it to either have it read the device signature or to have it be able to verify the data written to the AVR part. When avrdude reports an error I found that if I run the avrdude operation two or three times it will eventually be successful. When running avrdude on a Pi Zero I have sometimes had to reboot the Zero before avrdude would talk with an AVR after a previous successful programming cycle. I never needed to reboot the Pi when I was using a Pi model 1B.
I have not spent any time diagnosing this problem. It may simply be my use case where I have the AVR connected to external circuitry which feeds serial data to one of the pins used to program the AVR. If you experience a similar reliability issue you could disconnect some connections to the AVR that might interfere with communicating with the device or you can program the device out-of-circuit.
A brief word about permissions
To program AVR microcontrollers the avrdude program will need permission to access /dev/spidev0.0.
Buffering other signals
The 74LVC245 used in this project is capable of buffering eight signals but only four signals are needed to program AVR microcontrollers. Rather than waste half of the IC the circuit board was designed to allow the unused portion to be used to buffer other signals from (or to) the Raspberry Pi. The inputs for the unused buffers are pins 6, 7, 8, and 9 with the corresponding outputs being pins 14, 13, 12, and 11, respectively. Holes have been provided on the PCB for easy access to the input and output pins. The holes used for inputs and outputs are indicated by text in the silkscreen layer on the top side of the PCB.
Normally the input pins are tied to ground by traces on the top side of the PCB. Before you can use one of the unused buffers you must first cut the trace which is tying the input pin to ground. The trace must be cut between the GPIO header and the hole located between U1 and the GPIO header. Do not cut the trace between the input hole and U1.
Once the trace which was tying an input to ground has been cut you may use the input to buffer a signal from the Raspberry, or you may use the input to buffer a signal from an external circuit and use the corresponding output to feed the signal to the Raspberry Pi via the GPIO header.
You may notice there are five holes between U1 and the GPIO header. The fifth hole is there to provide easy access to ground in case you either need or want a ground reference for the (external) signals being fed to the input of U1. Two 4-pin headers were listed in the components list but you can use a 5-pin header for the inputs if you may need easy access to a ground reference on the header.