This is just going to be an instruction guide on how I got USB bootloading working. To make things as clear as possible, I’ll explain briefly how it works, then go on to the actual detailed instructions.

Before I begin, I’d like to start off with some vocabulary:

  • Flash memory – Memory in the MCU that stores the program. Flash is the type of memory… the important details are that it is re-programmable with just electricity.
  • Address – A location in memory. Memory starts at address 0x0000.
  • Address Pointer – Points to the current location in memory of the program (for the purpose of executing code).
  • Firmware – The program that is normally run in the MCU. It is usually located in the beginning address locations of Flash memory.
  • Bootloader – A program in flash memory that is able to reprogram the firmware.
  • Bootloader Section – Part of the flash memory that contains the bootloader.
  • Fuse – Important switches that control basic MCU operation.
  • Hex code/file – Contains the machine code for the firmware.
  • Program code – The actual c code for the firmware. This must be compiled to hex code using AVR-GCC.

Note: I did most things on Ubuntu 10.04, so my instructions pertain mainly to the *nix operating systems. Additionally, all of these instructions are specifically for the ATmega168 chip, although applying them to a different chip should not be too difficult. A lot of the following instructions are taken from here.


  1. Prerequisites – You must have the following installed:

    • AVR-GCC
    • libusb-dev
  2. Physical Setup (please excuse the poor wiring):
  3. For the simplicity of this tutorial, we’ll create a folder “hid” in the home directory.
    ~$ mkdir hid
  4. Download V-USB and extract to ~/hid.
    To test the functionality of V-USB, run a test HID-Mouse program:

    $ cd ~/hid/vusb-x/examples/hid-mouse/firmware
    Open usbconfig.h – Set the USB data pins (USB_CFG_IOPORTNAME = D, USB_CFG_DMINUS_BIT = 4, USB_CFG_DPLUS_BIT = 2)
    Open Makefile – edit (DEVICE = atmega168/ F_CPU = 12000000/ FUSE_H = 0xDE / FUSE_L = 0xDF / AVRDUDE = avrdude -c usbasp -p $(DEVICE))
    Obviously, you should modify these settings to your particular configuration. In particular, check this website out to see what fuse switches those values correspond to on your chip.

    $ make hex
    $ make program

    Replug the device and automagically the mouse will move on your screen.

  5. If the HID-Mouse works, you can now try getting the Bootloader to work. Download BootLoadHID and extract to ~/hid.
  6. Replace usbdrv from BootLoadHID with the one from V-USB:
    $ cd ~/hid/bootloadHID.x/firmware
    $ rm -r usbdrv
    $ cp -r ~/hid/vusb-x/usbdrv ~/hid/bootloadHID.x/firmware
  7. Open usbconfig.h – Change VENDOR and DEVICE name if you want
    Open bootloaderconfig.h – Set the USB data pins (USB_CFG_DMINUS_BIT = 4, USB_CFG_DPLUS_BIT = 2)
    Also in bootloaderconfig.h, change the bootLoaderInit() and bootLoaderCondition() as necessary. I also added a function bootLoaderExit() to tell me when the bootloader was finished. The bootLoaderCondition() is for telling the MCU to go into bootloader mode on some trigger (such as a button press).

For the ATmega168 Fuses, I used:

  • FUSEH = 0xDE
  • FUSEL = 0xDF
  • FUSEE = 0x00
  • (Note: there is no FUSEE definition in the makefile. You probably don’t need to change the extended fuse.)

Page… to be completed.