Forcing bootloader startup through program

Hello,
I am trying to find out if it is possible to trigger programmatically the double-tap on reset button function, implemented in modified version of Atmel's SAM-BA bootloader. In case this is not possible using the stock board setup, if this can be achieved by hardware or bootloader modifications.

Hi tolis81,

Here's some code that will programmatically place the board into bootloader mode after a system reset:

// Code to programmatically initiate bootloader mode after reset
#define BOOT_DOUBLE_TAP_ADDRESS           (0x20007FFCul)
#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))
#define DOUBLE_TAP_MAGIC 0x07738135

void setup() 
{
  pinMode(LED_BUILTIN, OUTPUT);               // Initialise the LED as an OUTPUT
}

void loop() 
{
  for (uint8_t i = 0; i < 5; i++)             // Blink the built-in LED for 5 seconds before reset
  {
    digitalWrite(LED_BUILTIN, HIGH);          // Turn LED on
    delay(500);                               // Wait half a second
    digitalWrite(LED_BUILTIN, LOW);           // turn the LED off by making the voltage LOW 
    delay(500);                               // Wait for a second
  }
  BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC;    // Start in bootloader mode after reset
  NVIC_SystemReset();                         // Reset the microcontroller
}
1 Like

For (Adafruit) SAMD51 devices (Feather M4, ItsyBitsy M4, etc) the 'magic' code is:

#define DOUBLE_TAP_MAGIC 			0xf01669efUL
#define BOOT_DOUBLE_TAP_ADDRESS     (HSRAM_ADDR + HSRAM_SIZE - 4)

unsigned long *a = (unsigned long *)BOOT_DOUBLE_TAP_ADDRESS;
*a = DOUBLE_TAP_MAGIC;
NVIC_SystemReset();

Hi qniens,

Thanks, good to know that the magic works on the SAMD51 as well.

MartinL

Hi MartinL and qniens. Thank you both for the answers. Hopefully I'll get my board this week for testing. The post delays are awful.

tolis81

Hey, I thought I'd try to do this on the SAMD51 Sparkfun Thing + and it doesn't seem to work. I've even had it print the number at the dbl tap address to confirm its correct, but the controller just resets normally. The only way I've gotten it to reset into the bootloader is by using these commented out lines (in Reset.cpp, or copied into my own function):

	// NVMCTRL->ADDR.reg  = APP_START;
	// NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY;

This does reboot into bootloader mode, but its locked into boot mode until an erase/upload is completed. Could the bootloader be slightly different on these particular devices?

@shalebridge Perhaps Sparkfun use a different magic number? I tried to find their bootloader source code on GitHub, but only the binaries were there.

Have you tried using the SAMD21's magic number instead?:

0x07738135

The SAMD51 Sparkfun Thing uses the SAMD51J20A version with more flash and RAM than the Adafruit boards, although the line supplied by @qniens should deal with this technicality:

#define BOOT_DOUBLE_TAP_ADDRESS     (HSRAM_ADDR + HSRAM_SIZE - 4)

You were on the right track @MartinL about the flash/RAM. Looks like the Thing+ Arduino library and bootloader code don't get along. I pulled the bootloader *.bin file and disassembled it in Ghidra. The Thing+ Arduino library code defines HSRAM_SIZE as 256k (0x40000), which matches what Sparkfun says on their website. The bootloader, however, has it set at 192k (0x30000) which matches what MicroChip says on the SAMD51J20A site. Using that number instead of the library "HSRAM_SIZE" got it working.

So if anybody else can't get the magic reset to work, it might be a bootloader/device library mismatch.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.