Skip to main content

Jesse Vincent

How to reboot an Arduino Leonardo / Micro into the bootloader.

2 min read

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.

// [...]
// 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.