adafruit / uf2-samdx1

MSC bootloader (based on UF2) for SAMD21
Other
210 stars 182 forks source link

reset into bootloader from user code? #185

Closed Knochi closed 1 year ago

Knochi commented 2 years ago

Hi,

is there a possibility to go into the bootloader from sketch? I know i read about that some time ago, but can't find the source anymore.

I'm planning to add a long button press + other button click to allow the user to update the firmware without pocking a needle in some hole.

dhalbert commented 2 years ago

If you write DBL_TAP_MAGIC into *DBL_TAP_PTR (which is at the very high end of RAM), and then do an NVIC_SystemReset(), it is as if the user double-tapped, and you will remain in the bootloader. Search the source for those symbols if you want more background on this.

Knochi commented 2 years ago

_'DBL_TAPPTR' was not declared in this scope

but i found this (link):

void reset_to_bootloader() {
  *(uint32_t *)(0x20000000 + 32768 -4) = 0xf01669ef;   // Store special flag value in last word in RAM.
  NVIC_SystemReset();    // Like pushing the reset button.
}
tfcroft4 commented 2 years ago

I asked a similar question with Adafruit forum for a QTPY project. The Adafruit bootloader can use UF2 files.

You need something like this:

//Double Tap used to branch to the bootloader so we can load a new uf2 file
// see https://forums.adafruit.com/viewtopic.php?f=62&t=151707
#if defined(__SAMD51__)
#define BOOT_DOUBLE_TAP_ADDRESS ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4))
#else
#define BOOT_DOUBLE_TAP_ADDRESS ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4))
#endif
#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *)BOOT_DOUBLE_TAP_ADDRESS))
#define DOUBLE_TAP_MAGIC                  0xf01669efUL // Randomly selected, adjusted to have first and last bit set 
void doUpload (char *args)
{
  //will call the boot loader but will pre-load the magic number so that the boot loader stays active
  //the  boot loader drive should appear on the PC
  //either load new firmware or cycle power to exit the boot loader
  Serial.println("Upload New  Firmware: ");
  Serial.print("The board will now reset and a new drive called ");
  #ifdef ADAFRUIT_QT_PY_M0
  Serial.print("QTPY_");
  #else 
  #ifdef ADAFRUIT_ITSTY_BITSY_M0  
  Serial.print("ITSY");
  #else
  Serial.print("??");
  #endif
  #endif
  Serial.println("BOOT will appear on your connected PC.");
  Serial.println("You can drag/copy a UF2 file onto the drive to update the Firmware.");
  Serial.println("The board will reboot after a successful upload.");
  Serial.println("To cancel upload turn power off then on again!");
  delay(1000) ; //delay to let Serial buffer clear
  //pre load the magic number normally used in bootloader first pass
  BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC;
  NVIC_SystemReset();      // processor software reset
}

I hope this helps Ted kitst.co.uk

dhalbert commented 1 year ago

Thanks for the comments. Closing as answered.