In addition to the sketches that you load onto your Arduino using the IDE, Arduino UNO (and newer) boards use a separate micro controller loaded with separate firmware for the purpose of communicating via USB. Here is how to build and program the stock Arduino firmware, which is useful when building an Arduino clone or for converting the UNO into something other than a serial USB device.
Overview
The Arduino UNO has two microcontrollers: the ATMEGA328 is the one used to store and run your sketches, and the ATMEGA8U2 is the middle man between USB and the serial IO of the ATMEGA328. By default, the ATMEGA8U2 contains firmware that makes the UNO appear as a serial USB device. Arduino boards prior to the UNO used a non-programmable FTDI chip for this purpose, but it is the replacement of this part with a programmable one that allows the UNO to appear as a device other than a serial port by loading it with new firmware.
Read more about it in Lady Ada’s UNO FAQ.
Prerequisites
- Linux. It is possible to re-program an Arduino using Mac and Windows, but the procedures here are for Ubuntu 12.04.
- An Arduino UNO (or newer?)
- An ISP programmer. Procedures will be shown for the STK500 but any avrdude ISP programmer will work.
- A soldering iron, solder, etc., and 6 x 0.100 pin headers.
Hardware Setup
By default, the ATMEGA8U2 on an UNO is loaded with a DFU bootloader and the LUFA USB stack configured as a serial device. While it is possible to update the USB code using the DFU loader, the only way to program the DFU code is via ISP.
Your ISP programmer should already be setup and working if you can successfully build and burn the bootloader, but since the bootloader is installed on the ATMEGA328 chip, and the USB subsystem is controlled by the ATMEGA8U2 chip, you cannot use the same ISP header.
Fortunately the UNO contains a footprint for adding the header – you just need to solder one in. See Lady Ada’s UNO FAQ for information about the ATMEGA8U2 and where to add the header.
Connect the ISP cable to the new header and check that everything is working:
$ avrdude -P /dev/ttyS0 -c stk500v2 -p at90usb82 -F avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e9389 avrdude: Expected signature for AT90USB82 is 1E 93 82 avrdude: safemode: Fuses OK avrdude done. Thank you.
Since avrdude doesn’t officially support the ATMEGA8U2, specify the at90usb82 part instead and use the -F flag to tell avr to ignore the device signature. Make sure the device signature matches (0x1E9389). If it reads 0x1E950F, you have the ISP connected to the ATMEGA328, not the ATMEGA8U2. If you program the USB code onto the ATMEGA328 by accident, you’ll overwrite the bootloader.
Software Setup
- Get the Arduino source from GitHub or copy it from the IDE install (/usr/share/arduino) into a directory of your choice – Let’s call it $SRC.
- Make sure you can build and burn the Arduino bootloader on the UNO. This will confirm that your build environment is setup correctly and your programmer is working.
- Download and unzip LUFA. You’ll need version 100807, even though there are newer versions. I like to unzip it into $SRC/hardware/arduino/firmwares.
Now modify the DFU and USB firmware makefiles to use LUFA and the STK500 programmer:
Set the LUFA path and avrdude parameters as necessary for your setup.
Update the UNO
As a final test of your hardware setup, upload the pre-built firmware to the ATMEGA8U2.
cd $SRC/hardware/arduino/firmwares/atmegaxxu2 avrdude -p at90usb82 -F -P /dev/ttyS0 -c stk500v2 -U flash:w:UNO-dfu_and_usbserial_combined.hex -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xF4:m -U lock:w:0x0F:m
This will write both the DFU bootloader and the USB serial code in one pass. Check that you can still upload sketches to the UNO using the Arduino IDE.
Now build the firmware:
cd $SRC/hardware/arduino/firmwares/atmegaxxu2/arduino-usbdfu make cd $SRC/hardware/arduino/firmwares/atmegaxxu2/arduino-usbserial make
To program the new firmware into the UNO, you have a few choices:
- Use ISP to write the DFU code (run “make program” in the arduino-usbdfu directory), then upload the USB code using dfu-programmer (see readme.txt in arduino-usbserial for instructions).
- Use ISP to write only the USB code (run “make program” in the arduino-usbserial dir). DFU programming will be disabled until the DFU code is re-flashed.
Since fiddling around to put the UNO in DFU mode looks spastic, I prefer (2). To restore the DFU loader, use (1) or see README.txt in $SRC/hardware/arduino/firmwares/atmegaxxu2 for how to upload UNO-dfu_and_usbserial_combined.hex.
There is a forum post which describes how to write both the DFU and USB code using ISP, but I was not able to make it work.