February 22, 2012

Arduino Mega Optiboot

I wrote a little sketch on my Arduino Mega clone coupled with an Ethernet Shield clone to reboot my remote desktop servers in case they lockup. The question is, what monitors the monitor? Of course, being a microcontroller, I figured the AVR surely must have some kind of watchdog function to reboot itself.

Unfortunately, the watchdog function didn't seem to work correctly. I simulated lockup conditions by using a long delay(). The watchdog happily triggered a reboot, but then the Mega gets into some kind of infinite reboot loop that could only be exited by uploading another sketch. (Just pressing reset or power recycle didn't work.) Upon further research, I discovered the watchdog doesn't function correctly on the Arduino Mega. The fix apparently is either to use Optiboot, or use a bootloader that has this bug fixed.

Optiboot comes by default for the Arduino Uno, and is actually available for the Arduino Mega, it's just not distributed in the Arduino IDE by default. I could either compile it by myself, or download it from the Optiboot repository. I would need to use an AVR programmer to flash the bootloader. Fortunately, my Arduino clone, the ET-EASY MEGA1280 is self-programmable by setting onboard jumpers.

So I flashed the Optiboot bootloader onto my Arduino Mega. But after the flashing was completed I discovered I could no longer upload sketches to it. It didn't feel completely "bricked" though, as I could re-flash the regular bootloader back to it and it worked again, but with Optiboot loaded, it didn't accept sketches any more. It kept giving me this error: sync avrdude: stk500_getsync(): not in sync: resp=0x00

It occured to me that because the board now contains Optiboot, I should be uploading at 115,200 kbps, and I should probably choose Uno as the board type. This is similar to how older boards such as the Arduino Duemilanove, when upgraded with Optiboot, effectively become the Uno and should be treated as an Uno in the Arduino IDE.

So I tried choosing Arduino Uno from the board type menu. It now complained that I don't actually have an Arduino Uno or a board based on the ATmega328P. The exact error was: avrdude: Expected signature for ATMEGA328P is 1E 95 0F  Double check chip, or use -F to override this check. I probably shouldn't override the check, since my ATmega1280 chip has much larger flash space, so I should probably just edit boards.txt instead.

Modifying the Arduino Mega section in boards.txt and changing the mega.upload.speed to 115200 fixed the upload problem. Even though Optiboot takes less space, I didn't modify the mega.upload.maximum_size value since I had no idea how much flash space Optiboot saved and what the maximum value should be, and 128K is enough for everyone. But since I have both regular Arduino Mega and Mega with the Optiboot, I decided to create a new section called Arduino Mega Uno.

The only issue I have with Optiboot is that once in a while, after upoading sketches or after plugging in the USB cable for USB power, the board doesn't start itself correctly. I need to push the reset button to run the sketch. The problem seems to be related to the serial port, since if I disable auto-reset (I have a jumper for that too.) it always works correctly. It also always starts correctly if I power up using an external power supply. Strangely enough, it seems to always start correctly too if I have shields installed, but I haven't tested this completely.

And yes, after installing Optiboot, watchdog works correctly now.

Edit: I noticed that the Optiboot repository actually contains a special boards.txt for Optiboot. However, the entry for Arduino Mega isn't quite correct, but it does contain a different maximum_size value. This is what I eventually put into my boards.txt.

megao.name=Arduino Mega Optiboot
megao.upload.protocol=arduino
megao.upload.maximum_size=130048
megao.upload.speed=115200
megao.bootloader.low_fuses=0xff
megao.bootloader.high_fuses=0xda
megao.bootloader.extended_fuses=0xf5
megao.bootloader.path=optiboot
megao.bootloader.file=optiboot_atmega1280.hex
megao.bootloader.unlock_bits=0x3F
megao.bootloader.lock_bits=0x0F
megao.build.mcu=atmega1280
megao.build.f_cpu=16000000L
megao.build.core=arduino
megao.build.variant=mega

No comments: