USB-AtmelPrg: Host Software for Flashing AVRs and Executing JTAG/SVF
USB-AtmelPrg is the native host software for the USB-AtmelPrg interface cable. It allows to in-system program ("flash") AVR (RISC) microcontrollers via SPI and can be used to program other parts like CPLDs by sending SVF files over the JTAG port.
Host Software for AVR Programming and Limited JTAG Support
I developed a host-side software for the interface cable which covers all functionality required to program AVR microcontrollers (erase, write, read flash and eeprom, read and write fuse bits; see below). Furthermore, the software allows to scan a JTAG chain for IDs and to execute SVF files (currently only for chains of length 1); see further down. The program features an interactive readline-based command line user interface with tab completion.
Note: Always use the latest software together with the latest
firmware. If the software complains about an "unknown board", you need
to update the firmware on the programmer.
(Due to changes in the transfer protocol, recent software versions don't
support old firmware versions.)
Download and Build
The program is distributed as source code, only. It should compile without problems on any Linux-ix86 platform using the GNU C++ compiler (gcc). Note that you need the specified support libraries as well.
NOTE: The program is known to not operate correctly with some earlier versions of these libraries (libftdi, libusb). I try to keep it compatible to recent versions of the libraries.
Supported AVR Microcontrollers
Support for additional AVR controllers will be added as soon as I need it. Currently, the usb-atmelprg host software supports the following controllers:
Note that generally no change in the firmware is required for support of additional controllers, but instead the corresponding driver/description has to be added in the host software. The required additions to the host source code are not very hard; just take an existing similar controller and enter the right flash sizes and fuse/lock descriptions. If you added support for a new controller, please send me a patch so that I can include it in the official source code distribution.
Known Bugs and Limitations
First Steps for AVR Programming
So, if you have built the programmer board, configured the USB chip and downloaded the firmware (both described on the firmware page) and successfully compiled the program above, you can do the first steps:
First, re-connect the USB cable to the programmer, switch it on (i.e. put S1 into state 3; you should see the LED MAINPWR going on) and watch the syslog output: You should see that the USB device is recognized by the kernel. But in particular, no module should be loaded and claim the device (especially not ftdi-sio) because in that case the usb-atmelprg program will no longer be able to access the USB connection. (If you used the USB IDs described on the firmware page, you should not get any trouble with that.)
Next, become root and start usb-atmelprg. If you did not chose to use the standard 0403:6002 USB IDs, you need to set the FTDI_USB env var first.
bash# # normally not needed: export FTDI_USB=0403:6002 bash# ./usb-atmelprg Opened USB connection to 0403:6002: Hardware: USB-AtmelPrg, Rev. 2/1 USB Atmel Programmer 1.0 by Wolfgang Wieser. Try `?' for help, ^D to quit. atmelprg> _
Now, the first step is to check if a programmer is connected. You normally need not issue the ident command since it is done automatically when needed but it comes handy for initial testint:
atmelprg> ident Connected to 0403:6002 (USB-AtmelPrg, Rev. 2/1): Device: USB AtmelPrg Rev 2.2 Vendor: Wolfgang WIESER, 04/2007 Firmware version: 0x202 Protocol version: 5 atmelprg> _
If you see something like that (note that these strings except those in the first line are compiled into the firmware and not into the USB controller), then this is already a good sign.
Next, connect an AVR-based device to the 9-pin SUB-D connector and set the switch S2 correctly (see circuit page). The LED DEVPWR should be illuminated. Try to connect to the chip there. I assume the RESET pin is not externally controlled:
atmelprg> connect Atmel chip: Name: ATMega8515 (Vendor: Atmel) Flash: 8192 bytes [0x1000 words] Pages: 64 bytes EEPROM: 512 bytes atmelprg> _
Note also that it is normally not necessary to use the connect command since it is executed automatically when needed. However, some mostly older AVRs (like the AT90S2313) may have trouble entering the programming mode if the RESET line is not pulsed high and low before; in this case you may need to use 2 commands to connect: rh, then connect ("rh" is the short form for "r h"; this works because the connect command will automatically set the RESET line LOW; it is assumed that the RESET line is not externally controlled).
If the RESET pin is externally controlled (i.e. the programmer device cannot simply tie it low or high), use the command set ext_reset 1 before doing connect and make sure to get RESET LOW before trying to connect (otherwise it will fail).
Now, we can e.g. read the flash content, dump it, load a file to program, erase the chip download the flash content and so on... The commands would be (with output omitted):
atmelprg> readflash atmelprg> dump flash atmelprg> load firmware.bin atmelprg> erase atmelprg> writeflash firmware.bin atmelprg> _
(Make sure to program the flash content binary and not an Intel HEX file (ihx) and also not an ELF format file; see compiling AVR firmware.) Finally, when done, or when the device with the new firmware needs to be tested, you must explicitly disconnect the programmer. This is done using the dc command.
atmelprg> dc Programmer status: SCK: in:HIGH (P) MOSI: in:HIGH (P) RESET: in:HIGH (Z) D6: in:HIGH (Z) D7: in:HIGH (Z) D8: in:HIGH (Z) LED: off MISO: LOW atmelprg> _
You can explicitly set the RESET pin LOW, HIGH and into High-Z state using the commands r l, r h and r z, respectively. This can come handy to manually reset the device to be programmed.
Finally note that there is tab completion, i.e. pressing tab should do completion on things which make sense (does not yet work perfectly) and that you can get a short online help using the ? command. To quit, just use Control-D as usual.
Now, let us quickly program the fuse bits to migrate from the 1MHz
internal RC oscillator to the 8MHz one.
The fuseL value used here is for the ATMega8515 (and ATMega8);
other chips use similar fuse bit values; check the data sheet to be sure.
atmelprg> getfl Lock bits: 0xff (programmed=0) BLB1 2,1: 11 (see p.177) BLB0 2,1: 11 (see p.177) LB 2,1: 11 (unrestricted memory access) Fuse low bits: 0xe1 (programmed=0) BODLEVEL: 1 (brown-out level 2.7V, see p.45) BODEN: 1 (brown-out detector disabled) SUT 1,0: 10 CKSEL 3..0: 0001 (internal RC osc at 1 MHz) Fuse high bits: 0xd9 (programmed=0) S8515C: 1 (AT90S4414/8515 compat mode disabled) WDTON: 1 (WDT off) SPIEN: 0 (SPI enabled) [readonly] CKOPT: 1 (small output swing, see p.34) EESAVE: 1 (EEPROM erased at chip erase) BOOTSZ 1,0: 00 (boot size 1024 bytes, see p.175) BOOTRST: 1 (reset vector at address 0) atmelprg> _
What we need to do is to change the CKSEL value from 0001 to 0100 leaving
all other values unchanged.
You may use setfl help for more information.
atmelprg> setfl fuseL=0b11100100 Fuse low bits: 0xe4 (programmed=0) BODLEVEL: 1 (brown-out level 2.7V, see p.45) BODEN: 1 (brown-out detector disabled) SUT 1,0: 10 CKSEL 3..0: 0100 (internal RC osc at 8 MHz) Not actually writing anything ("!" not specified). atmelprg> setfl fuseL=0b11100100 ! Fuse low bits: 0xe4 (programmed=0) BODLEVEL: 1 (brown-out level 2.7V, see p.45) BODEN: 1 (brown-out detector disabled) SUT 1,0: 10 CKSEL 3..0: 0100 (internal RC osc at 8 MHz) Writing: [fuseL] atmelprg> _
Note that by writing improper fuse/lock bits (like wrong clock select, disabling reset pin, disabling SPI [should not be possible via SPI]) you can render your microcontroller inaccessible by the programmer. It is therefore highly recommended to first simulate and double-check the settings.
Similarly, one would use 0b11101000 for external clock but after that you cannot go on talking to the controller unless you actually have an external clock connected to the Atmel controller you wish to program.
Command sequencing: Since version 0.5, you can use the semicolon to separate commands. Like that, you can re-execute a set of commands simply by pressing up-arrow (previous command in readline history) and enter/return. Common example:
atmelprg> load firmware.bin ; erase ; writeflash firmware.bin ; cmpflash firmware.bin ; dc
If you experience trouble with sequencing for commands which work when executed one-by-one, it may help to add a delay with optional delay time in msec:
atmelprg> load firmware.bin ; erase ; delay ; writeflash firmware.bin ; ...
SPI: IO Speed Selection
Since software version 0.7 and firmware Rev 1.2, you can select different IO speeds for communication between the programmer and the device to be programmed. These are set using the set io_speed command, e.g.
atmelprg> set io_speed normal
It is important to understand the theory behind serial IO speed: The controller to be programmed runs at a certain internal frequency f. (In case things like "clock division by 8" (e.g. ATtiny2313) are activated, the internal clock is the divided/slower clock.) In order for serial communication to work, the LOW and HIGH pulses of the SCK signal pin must be several clock cycles wide at least (2 for most AVRs at 1MHz, see data sheet). Hence, LOW and HIGH times must be at least 2/f (seconds).
The set io_speed command accepts an argument which is the time in microseconds (usec) to keep SCK LOW/HIGH. This must be at least 3. For faster operation, use the special keywords normal (default), fast and extreme; see table above. Note: The numerical value specifies a delay in usec, hence larger values make things go slower.
NOTE that you should always be on the safe side and make the timings slightly longer than required especially since the internal RC oscillators are not very precise. This is also the reason for the 1/8usec safety margin in the normal and fast modes.
If you change the IO speed while being connected to the AVR, the software will request a re-connect to be sure that the communication works with the selected speed. If you have trouble connecting to a device, try a slower IO speed (i.e. larger number).
Note: If you didn't understand everything, memorize that if you buy a recent AVR (like ATMegaXXX or ATtinyYYY) with an internal RC oscillator, it will run at 1MHz as of factory defaults and the default setting for the IO speed (normal) should work just fine.
First Steps for JTAG/SVF Programming
First, after connecting the cable to the JTAG port of the device to be programmed, we may want to see what device is connected. To read the so-called IDCODE, use jid. If the software knows the IDCODE, it will display additional information, e.g:
atmelprg> jid JTAG ID code: 0x59604093 = 01011001011000000100000010010011 Version: 5 Manufact: 0x049 (Xilinx) Part num: 0x9604 (XC9572XL) Marker: 1 (should be 1) atmelprg> _
Note that for SVF downloading it is not necessary that the usb-atmelprg software "knows" the connected device.
SVF (serial vector format) is a JTAG output specification. SVF files can be generated by CPLD/FPGA design/programming software as supplied by the respective vendors of such devices (such as ISE WebPACK from XILINX and similar tools from Altera or Lattice).
In order to execute an SVF file, first connect the CPLD (or whatever you wish to program) to the USB-AtmelPrg interface cable and then issue the svfprog command in the host software. Example:
atmelprg> svfprog test.svf Programming SVF file: 186450 bits in 808 blocks... Elapsed: 7927 msec (slept 2761 msec); rate: 9.810644 msec/pack atmelprg> _
JTAG/SVF: Bugs and Limitations
Not all the SVF functionality is supported currently: