Using an Arduino to burn bootloaders

A few years ago, my wife decided to buy me a bare bones, electronics learning kit called a Nerdkit. You can think of it as an Arduino on a breadboard. Included in the kit are various sensors as well as a wonderful little guide walking you through the setup and introducing a lot of basic electronics concepts like Ohms Law. Whereas an Arduino is a great jumping off point for creating lots of amazing projects quickly, it abstracts a lot of the nitty-gritty that I like to get into. It's kind of like learning to program in BASIC before tackling a lower-level language; more programmers than ever get through their entire career without knowing C, and I'm sure a lot of electronics hobbyists don't care to learn AVR-C or what makes a bootloader work. This is why I like the Nerdkit so much: you're essentially building an Arduino from scratch.

Whilst tinkering with said Nerdkit in the first few months, I managed to corrupt the bootloader on the chip. No matter what I tried, I couldn't flash new programs. Hours of frustration later, the Nerdkit ended up in a box in favor of less complicated things. Fast-forward a few years, and I find the Nerdkit and all the pieces in a box, and the memories of defeat come flooding back and so I decided this time I was going to get it working.

Hours of Googling later, I discvoered it's possible to use the Arduino to burn the Nerdkits bootloader onto the ATMega168 microcontroller that comes with the kit. Much trial-and-error was required, as well as the discovery that a modern Macbook Pro just doesn't seem to be too accurate about honoring the delicate timings necessary to write to the chip. I had substantially better luck using my Windows 7 desktop for the job. Finally, it seems some people have issues using an Arduino Uno or newer as an ISP

The base instructions are here. I attempted to follow the "Minimal Circuit" example, omitting the capacitors and the crystal oscillator (which happens to be in the Nerdkit). However, nothing I tried would work. I ended up plugging the oscillator between pins 9 and 10 on the chip, as well as using the capacitor from the kit between pins 7 and 8. I'm not actually sure that was mandatory, but it didn't hurt anything.

Steps: Upload the "Arduino as ISP" sketch (in the Examples) to your Arduino. Wire the Arduino as per the instructions above, making sure to plug in the oscillator between pins 9 and 10 Locate your bootloader.hex file. In the case of the Nerdkit, this is "foodloader.hex" under the "bootloader168" path. You'll need to open a terminal / command line. Alternatively, you can modify the foodloader Makefile. * Either run the follow commands or write them to your Makefile:

    # You need to supply the full path to your serial cable. On Windows, it will be a COM port like "COM3"
    # You may need to tinker with the baudrate (-bXXXXX)
    AVRDUDEFLAGS=-cavrisp -patmega168 -P/dev/cu.usbserial-A70063hT -vvvv -b19200

    all: fuses install

      avrdude ${AVRDUDEFLAGS} -U lock:w:0x2f:m -U efuse:w:0x00:m -U hfuse:w:0xd5:m -U lfuse:w:0xf7:m
      avrdude ${AVRDUDEFLAGS} -U flash:w:foodloader.hex:a

    # I had issues giving a full path to the .hex file, so I found it was easier to have it locally

If everything goes well, you should see a message saying everything was verified. The most common issues I saw were "programmer not responding" and "invalid signature." Once I'd wired everything as above and got everything written, it worked great. The caveat is it took numerous tries (20 or more) before it had written successfully. I'm inclined to blame the USB to Serial interface more than anything else, though I found others online thinking it might be power fluctuations from the increased demand of burning the bootloader. The rationale made sense to me, so this is when I inserted the capacitor back into the circuit. I suspect if you have both the capacitors recommended in the Arduino tutorial, you'll have an even easier time. One article even suggested providing external power to the ATMega168, and I would have attempted this had this path not panned out.

After more fussing, I was able to reflash the "initialload" program from the Nerdkits code base. However, I had to modify THAT Makefile as well to separate the erase and flash steps with a sleep in between. The follow modification worked for me about 1 in 5 tries.

    GCCFLAGS=-g -Os -Wall -mmcu=atmega168
    LINKFLAGS=-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm
    AVRDUDEFLAGS=-c avr109 -p m168 -b 115200 -P /dev/cu.usbserial
    LINKOBJECTS=../libnerdkits/delay.o ../libnerdkits/lcd.o ../libnerdkits/uart.o

    all:  initialload-upload

    initialload.hex:  initialload.c
      make -C ../libnerdkits
      avr-gcc ${GCCFLAGS} ${LINKFLAGS} -o initialload.o initialload.c ${LINKOBJECTS}
      avr-objcopy -j .text -O ihex initialload.o initialload.hex

    initialload.ass:  initialload.hex
      avr-objdump -S -d initialload.o > initialload.ass

    initialload-upload: initialload.hex
      avrdude ${AVRDUDEFLAGS} -e
      sleep 1.5
      avrdude ${AVRDUDEFLAGS} -D -U flash:w:initialload.hex:a -v

    # I chose the sleep value randomly. Also note the -D flag on the flash, which tells avrdude not to erase the chip.

If you don't intend to use the chip with the Nerdkit, or you're done tinkering with it and would like to repurpose it for another project, you should be able to use this method to burn any other bootloader, including the Arduino bootloader.

I also own a Pocket AVR Programmer which I intended to try if I couldn't get the Arduino method to work. The Sparkfun model is specifically designed to avoid a lot of the ad-hoc nature of the above method, though I found the internet lacking in help if you didn't specifically want to use to burn a bootloader over the ISP pins of the Arduino board.


Comments powered by Disqus