Jonathan Thomson's web journal

Project Ouroboros — Reflashing a betemcu USBasp Programmer August 18, 2011

Filed under: Electronics — jethomson @ 11:40 pm

USBasp is a free, open source firmware and reference design for implementing a USB AVR programmer. It uses simple circuitry and an ATmega8 or ATmega*8 for interfacing with the USB host. A variety of inexpensive boards ($6 US) based on the USBasp project can be purchased from many eBay sellers. Re-programming one of these boards can often be an effective solution for a one-off project where the cost of a full development board or the time consumed designing and assembling a custom board is prohibitive. They can even be made to work with Arduino. This article focuses on the board pictured here. Note that there are at least two versions of this board.


V-USB — a firmware-only implementation of a low-speed USB device for Atmel AVR microcontrollers.
in-circuit programmer — a device for burning code and changing fuse settings on a microcontroller which remains in its application circuit.
USBasp – a USB in-circuit programmer for Atmel AVR microcontrollers that utilizes V-USB.
boot loader — a bit of firmware capable of burning code onto the same microcontroller on which it resides. A boot loader allows new code to be uploaded to a microcontroller without an external programmer.
USBaspLoader – a USB boot loader that follows the USBasp protocol.

It’s possible to erase the USBasp firmware and load a new program onto the board via the 10 pin header. First insert a jumper wire into the two holes circled in yellow in the picture above. Doing this connects RST on the 10 pin header to PC6 (RESET). Now you can use a second programmer to burn the code. However if you put USBaspLoader onto the board you can use AVRDUDE or Arduino to upload programs directly over USB without having to use an external programmer. Once you have the USBaspLoader on the board there is still enough room left to re-upload the USBasp firmware so that the board can function as an external programmer again. I call this Project Ouroboros because it’s a play on the word asp and seeming recursiveness of using USBaspLoader to put USBasp onto a USBasp programmer.


Getting started
First you’ll need a USBasp programmer (hereafter betemcu board) and a second, external programmer (hereafter primary programmer) capable of programming AVR microcontrollers over SPI. Next you should test out your betemcu board to make sure it’s not defective. Before you load new code onto your betemcu board you should use the primary programmer and AVRDUDE to save the betemcu board’s factory installed firmware to your computer and discover its original fuse settings. Doing this will allow you test whether the device is still functional by attempting to restore it to a known good state by writing back the original firmware and fuse settings. The following command will save the betemcu board’s firmware and display its fuse settings. The -c programmer-id option is the ID of the primary programmer.

avrdude -p atmega8 -c programmer-id -v -U flash:r:betemcu_factory_firmware.hex


Fuse settings for burning code to the betemcu board with an external programmer
If you are unfamiliar with microcontroller configuration fuses, then please visit the relevant articles in the Links section to learn more about them. You should also use a fuse calculator to double check fuse settings before applying them. The original settings for my betemcu board were hfuse = 0xD9 and lfuse = 0xFF but these leave CKOPT unprogrammed which should be set for crystals faster than 8 MHz. The makefile for USBasp uses hfuse = 0xC9 and lfuse = 0xEF but these settings don’t work because the start-up delay isn’t long enough, in fact they (recoverably) brick the betemcu board. Setting the fuses to hfuse = 0xC9 and lfuse = 0xBF sets a proper start-up delay and enables CKOPT. These also set a brown-out detection level of 2.7 V which is necessary if you want to use the onboard 3.3 V regulator for power. Here’s an example hex file that blinks the LEDs on a betemcu board. (mirror)

high fuse: 0xC9
low fuse: 0xBF

avrdude -p atmega8 -c programmer-id -U hfuse:w:0xC9:m -U lfuse:w:0xBF:m
avrdude -p atmega8 -c programmer-id -U lock:w:0x3F:m
avrdude -p atmega8 -c programmer-id -v -U flash:w:betemcu_blink.cpp.hex


To restore the boot loader:

avrdude -p atmega8 -c programmer-id -v -U flash:w:betemcu_factory_firmware.hex


If you’ve downloaded the USBasp package, you can also restore the boot loader with a precompiled hex file:

avrdude -p atmega8 -c programmer-id -v -U flash:w:usbasp.atmega8.2011-05-28.hex


Modifications required to run USBaspLoader on the betemcu board
The unmodified version of USBaspLoader connects PD2 and PD4 to the USB data plus and data minus lines. However the betemcu board connects PB1 and PD2 to USB data plus and PB0 to USB data minus. Therefore the USBaspLoader code needs to be changed to use the same pins. Here’s a snippet of bootloaderconfig.h with the changes already made.

/* This is the port where the USB bus is connected. When you configure it to
* "B", the registers PORTB, PINB and DDRB will be used.
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
* This may be any bit in the port.
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
* This may be any bit in the port. Please note that D+ must also be connected
* to interrupt pin INT0!

Vanilla USBaspLoader is set up so that it will only enter self-programming mode (i.e. listen for a program being uploaded and write it to the flash) if PD7 is held low after pulling the reset pin low (i.e. an external reset) occurs. Therefore you will have to make a couple of modifications to the betemcu board. First you’ll want to add a normally open pushbutton connected to the reset pin and ground for producing an external reset. Soldering the pushbutton connection at the reset pin’s pull-up resistor is easier than soldering it directly to the pin.


For the second modification you’ll have to determine how you want to signal the boot loader to wait for a program. The typical method is to use a jumper to connect PD7 to ground. The NC (not connected) pin of the 10 pin header is conveniently located 0.1″ from one of the header’s ground pins so running a mod wire from PD7 to NC is a simple way to add a jumper header. However, if you plan on interfacing the betemcu board with another circuit through the 10 pin header by using a 10 pin IDC you will want to add the jumper header somewhere else on the board because of the difficulty of inserting and removing the 10 pin IDC while the USB connector is plugged in. Using a pushbutton connected to PD7 and ground instead of a jumper is also an option, but you’ll have to keep the pushbutton pressed until AVRDUDE has finished.

Here’s a picture of my modified board. At first I was using a jumper to connect PC2 (orange wire to NC) to ground, but later I decided to add a second pushbutton to signal the boot loader to wait for a program to be uploaded. The brown and blue wires are for I2C and not a necessary modification.


The pin used to signal the boot loader can be easily changed by modifying bootloaderconfig.h. If you want to use a different pin make certain it’s not already being used for another function by consulting USBasp schematic and by carefully examining the betemcu board. Keep in mind that pins at the corners of the ATmega8’s package are easier to solder to.

Compiling a new hex file from the USBaspLoader source also requires a few changes to the Makefile. I’ve created a package of the vanilla version of USBaspLoader preconfigured to work with the betemcu board. I’ve also included a pre-compiled hex in case you have difficulty compiling. Here’s a link to the preconfigured vanilla USBaspLoader package. (mirror)


Alternate version of USBaspLoader
I wasn’t happy with using a jumper (or pressing and holding a pushbutton) to signal the boot loader to enter self-programming mode (SPM). So I’ve made some changes to the vanilla version and packaged them as an alternate version of USBaspLoader. The alternate version allows you to enter and stay in self-programming mode by pressing and releasing a pushbutton, which is a more typical method used by other USB development boards with microcontrollers that have a HWB pin. I’ve also added an option that compiles the boot loader so that it always enters SPM after every reset and uses a timeout to exit the boot loader, which makes adding a jumper (or a second pushbutton) unnecessary. This is the method that should be most familiar to Arduino users. For the betemcu board I made a few more modifications to utilize the board’s LEDs. Click here to download the alternate version of USBaspLoader configured for the betemcu board. (mirror) Here’s a sample of some of the changes I made:

/* If TIMEOUT_ENABLED is defined to 1 then the boot loader will always load
* and stay active until the programmer closes the connection or the time
* out period has elapsed. Since the boot loader always loads there is no
* need for a jumper on the bootLoaderCondition() pin. Costs ~108 bytes.
/* The number of seconds the boot loader waits before exiting if no activity
* has occurred during the timeout interval. If TIMEOUT_ENABLED is defined
* to 0 this define will be ignored. Maximum value is 255 seconds.
/* If USING_PUSHBUTTON is defined to 1, then a press and release of a
* pushbutton on the bootLoaderCondition() pin can be used to signal that
* you wish to enter the boot loader. If USING_PUSHBUTTON is defined to 0,
* then you must use a jumper or the pushbutton must be pressed and held
* for the duration of the programming (failing to do so will result in
* the boot loader exiting prematurely).


Fuse settings for burning USBaspLoader to the betemcu board with an external programmer
The USBaspLoader hex file for an ATmega8 at 12 MHz is around 1900 bytes so the 2 kB boot loader section is required. After flashing a boot loader, the proper lock bits should be set so that the boot loader isn’t overwritten when you use it to upload a program. These fuses set a boot flash section size of 1024 words (2048 bytes) and a start-up delay of 64 ms.

high fuse: 0xC8
low fuse: 0xBF
lock bits (unlock): 0x3F (AVRDUDE)
lock bits (lock): 0x0F (AVRDUDE)

lock bits (unlock): 0xFF (AVR studio)
lock bits (lock): 0xCF (AVR studio)

avrdude -p atmega8 -c programmer-id -U hfuse:w:0xC8:m -U lfuse:w:0xBF:m
avrdude -p atmega8 -c programmer-id -v -U flash:w:alternate_USBaspLoader_betemcu_pushbutton.hex
avrdude -p atmega8 -c programmer-id -U lock:w:0x0F:m


If you don’t want to add a SPM jumper or button, you can use the timeout boot loader.

avrdude -p atmega8 -c programmer-id -U hfuse:w:0xC8:m -U lfuse:w:0xBF:m
avrdude -p atmega8 -c programmer-id -v -U flash:w:alternate_USBaspLoader_betemcu_timeout.hex
avrdude -p atmega8 -c programmer-id -U lock:w:0x0F:m


Flashing a program with USBaspLoader
Now that you have USBaspLoader on your betemcu board you can flash new programs to it directly over USB. Here’s a link to a program from the V-USB project that emulates a mouse. (mirror) To instruct your board to enter self-programming mode, start by pressing and holding the program button, next press and release the reset button, then release the program button. The green LED should turn on indicating the board is ready for a program upload. Upload the hex file using the following command. If the upload is successful you should see the mouse cursor move in a circle.

avrdude -p atmega8 -c usbasp -v -U flash:w:vusb_mouse_example.hex


You can also upload the USBasp firmware onto the board to restore its ability to program other AVR microcontrollers.

avrdude -p atmega8 -c usbasp -v -U flash:w:usbasp.atmega8.2011-05-28.hex


With USBaspLoader on the board it is now compatible with the Arduino programming environment. You must add some entries to boards.txt to be able to upload a sketch within the Arduino IDE. Follow this link for an explanation of the variables used in boards.txt. Put the following at the top of boards.txt:

############################################################## w/ ATmega8 at 12MHz

(Update: I didn’t have to but you may also need to add a few lines to programmers.txt and one more line to boards.txt to get things working. See John B├Ąckstrand’s comments below.)

Then under Tools->Board select "USBaspLoader w/ ATmega8 at 12MHz". It is normal to get this message: "avrdude: warning: cannot set sck period. please check for usbasp firmware update." Note that you’ll need to connect a USB to serial adapter to RX and TX if you want to send data over the UART (i.e. Serial.print()). Also note that the ATmega8 is missing some of the features the ATmega*8 series of chips have. For example, the ATmega8 doesn’t have PWM capability on Timer0. Therefore, this board won’t work with some Arduino sketches.


You can also upload the sketch from the command line with the following command. Notice that you don’t need to set any fuses, in fact the boot loader is incapable of changing fuses.

avrdude -p atmega8 -c usbasp -v -U flash:w:betemcu_blink.cpp.hex


Here are a couple of source packages of concentrated evil. (mirror)– This is a modified version of the firmware used in the Haunted USB cable. It was changed slightly so that it works on the ATmega8. For some reason it doesn’t work in X windows. (mirror)– Jack prints out “All work and no play makes Jack a dull boy.” 13 times while randomly pressing space and backspace. It is based on the USB Business Card firmware.


AVR Fuses HOWTO Guide
LadyAda’s AVR Tutorial — Fuses
A very helpful fuse calculator
If you’d like a full V-USB development board check out USnooBie.