Saturday, January 29, 2011

In Circuit Programmer (ISP) How To: Atmel AVRISP mkII

So far in our tutorials on setting up and programming the AT90USB162 development board we've taken advantage of the built-in loader via USB and dfu-programmer.  Loading code via USB is convenient, on the other hand there are a number of things that can't be done via USB and the dfu-programmer software.  AVR microcontrollers in addition to having flash memory (where your program is stored) and EEPROM (where your data is stored) also have between one and four configuration bytes as well as a three device signature bytes.  In order to read and write these bytes you need to use an In Circuit Programmer or "ISP" for short.  There are a huge variety of programmers that support AVR microcontrollers for purposes of this tutorial we will discuss Atmel's AVR ISP mkII programmer.  There are two types of ISP header commonly used on AVR boards, 2x3 and 2x5.  If you have a board, like our AT90USB162 board, with a 2x5 header you will need to buy an adapter to connect the 2x3 connector on the mkII with your board. sells 2x3 to 2x5 adapter for $6.  Once you have your mkII, Adapter, and board attach the mkII to the board and then to your computer via a USB cable.  You will also need a second USB cable or 9v power supply to power your development board.  The mkII will *not* supply power to your AVR and if you don't power it separately programming the device will fail.

Now that we have the hardware hooked up it's time to setup the software to drive the mkII.  There are a couple pieces of software that will drive the mkII in Linux we'll be using AVRDude for this tutorial.  First you will need to get the source code for avrdude.  At the time of writing the latest version is 5.10.  Next we'll untar, configure, and compile as follows...

tar -xzvf avrdude-5.10.tar.gz
cd avrdude-5.10
sudo make install

To test that everything is working correctly lets read the device signature bytes using the following command...

avrdude -p at90usb162 -c avrisp2 -P usb -U signature:r:signature.txt:h

Avrdude sometimes takes a moment to complete when it does the result of the above command should be a text file, "signature.txt", containing three hexadecimal values corresponding to the signature bytes of your AVR chip.  Breaking down the above command the -p option specifies the type of AVR we are programming, the -c specifies the type of programmer, the -P specifies the way the programmer is connected to the computer and the -U specifies the operation to be performed.  The avrdude man page gives a listing of supported AVR chips and programmer devices and their associated command line option.

The last part of the avrdude command, the -U may look a little complex but it's simple once we break it down.  There are four parts to it each separated by a colon.  The first part specifies which of the locations of the AVR's memory will be operated on, common values are eeprom, flash, efuse, hfuse, lfuse, lock and signature.  A full list of values is in the man page.  The next field specifies the operation, either r, w, or v which stand for "Read", "Write", and "Verify".  The third field is the name of a file to be used on either input or output depending on the specified operation.  The last field is the format of the input / output file.  Common options for the format are either "h" for hexadecimal or "i" for Intel Hex format.  The code we loaded using dfu-programmer is previous tutorials was in Intel Hex format and the same format is supported by avrdude.

We can use avrdude instead of dfu-programmer to flash the AVR as follows.  For this example we'll use the code from the "Hello World" example.  Build the example code.  The output should be a file called "light.hex".  The following avrdude command will flash your AVR with the light.hex code...

WARNING: Using the ISP to flash your AVR will delete the USB boot loader code and dfu-programmer will no longer work.

avrdude -p at90usb162 -c avrisp2 -P usb -U flash:w:light.hex:i

The other common task you may need to do and one of the main reasons you will need an ISP is to read and write the "fuse" and "lock" bytes.  These configuration bytes configure various options like the clock divider as well as the code protection on the AVR.  The exact purpose of each of the bits within these bytes is described in the AVR's datasheet.  For the AT90USB162 the relevant information is in Chapter 25, titled "Memory Programming".

Of particular note is bit seven of the low fuse (aka: lfuse) byte, this is the CKDIV8 bit.  When programmed this option divides the system clock rate by 8.  AVR's come with this fuse bit programmed by default so even though the AVR data sheet says that the internal oscillator runs at 8Mhz that is before it is divided down.  That means that out of the box AVR's have an effective clock rate of 1Mhz.  (Note: the clock rate can also be effected by the System Clock Prescale Register, "CLKPR")  The exact clock rate your AVR runs at will be important when you start doing more complex programming tasks that involve precise timing such as serial communications.  The following avrdude command will read the low fuse byte...

avrdude -p at90usb162 -c avrisp2 -P usb -U lfuse:r:lfuse.txt:h

After running the above command the value of the low fuse byte will be stored in the file lfuse.txt as a hexadecimal number.  The default value for an AT90USB162 will be 0x5E.  In binary form 0x5E is 01011110 the left most bit is bit 7 and corresponds to the CKDIV8 bit discussed earlier. To disable the CKDIV8 option we would reprogram the lfuse to 11011110 or 0xDE.  It's important to note that the AVR data sheet uses the terms "programmed" and "unprogrammed" to denote the two states of the fuse bits.  Perhaps confusingly, "programmed" refers to a 0 value for the bit while "unprogrammed" refers to a value of 1.  To modify the lfuse byte use the following command. 

avrdude -p at90usb162 -c avrisp2 -P usb -U lfuse:w:0xde:m

In this case instead of giving a file name we are giving the value to write on the command line itself.  The "m" given for the 4th parameter of the -U argument means that the 3rd parameter to -U is the actual value to write to the lfuse and not a file name to read from or write to.
Note: There seems to be a bug in avrdude that gives the error "avrdude: fileio: invalid operation=0" if you try to write fuse values by reading them from a file, ie: lfuse:w:somefile.txt:h instead of using the "m" command line format as we did above.

That covers the basics of how to use an In System Programmer (ISP) to program and read flash, EEPROM, and configuration bytes from your AVR.