How to reboot an Arduino Leonardo / Micro into the bootloader.
One of the things we're building for the Keyboardio Model 01 is an interactive keyboard shell that I've provisionally named "quiche".
Today, I implemented functionality to allow the user to reboot the ATmega32U4 inside the keyboard into the Caterina bootloader so the user can upload new firmware.
It took a lot more time than it should have to find the right magic incantations to get the bootloader to stay in firmware upload mode. (In the end, it was just a matter of looking at CDC.c inside the Arduino core.)
So that nobody else has to stumble through this as I have, I've pasted my solution below.
#include <avr/wdt.h>
// [...]
// Set the magic bits to get a Caterina-based device
// to reboot into the bootloader and stay there, rather
// than run move onward
//
// These values are the same as those defined in
// Caterina.c
uint16_t bootKey = 0x7777;
uint16_t *const bootKeyPtr = (uint16_t *)0x0800;
// Stash the magic key
*bootKeyPtr = bootKey;
// Set a watchdog timer
wdt_enable(WDTO_120MS);
while(1) {} // This infinite loop ensures nothing else
// happens before the watchdog reboots us
Solutions that didn't work for for me included:
- Writing raw assembler like:
asm volatile ("jmp 0x7800"); // This address also happens to be bootloader-size dependent
- Tweaking MCUSR to try to convince the bootloader that an external reset had been initiated.
- Previous: Model 00
- Next: No, I'm not actually blogging again