Bootloader

Please tell us which board you are using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
RogierWeekers
 
Posts: 6
Joined: Wed Jan 26, 2022 8:43 pm

Bootloader

Post by RogierWeekers »

Is it possible to go into bootloader mode via software. My setup is with a touch panel, which is build into a case, now, if I need to change the code I have to open the case so I can push the button twice. It would be convenient if a dedicate button on the touch panel could be used to switch over.

User avatar
westfw
 
Posts: 2010
Joined: Fri Apr 27, 2007 1:01 pm

Re: Bootloader

Post by westfw »

On which board?

User avatar
RogierWeekers
 
Posts: 6
Joined: Wed Jan 26, 2022 8:43 pm

Re: Bootloader

Post by RogierWeekers »

Metro M0 express

User avatar
adafruit_support_carter
 
Posts: 29473
Joined: Tue Nov 29, 2016 2:45 pm

Re: Bootloader

Post by adafruit_support_carter »


User avatar
RogierWeekers
 
Posts: 6
Joined: Wed Jan 26, 2022 8:43 pm

Re: Bootloader

Post by RogierWeekers »

Is there a library for C++ (visual studio micro) ?

User avatar
User_UMjT7KxnxP8YN8
 
Posts: 323
Joined: Tue Jul 17, 2018 1:28 pm

Re: Bootloader

Post by User_UMjT7KxnxP8YN8 »

I haven't used the M0 but I force reboots (which involves running the bootloader) on the Metro M4 by setting up the Watchdog Timer (WDT) then entering a tight loop that causes it to time out.

You can find my WDT code at https://github.com/SapientHetero/Watchd ... SAMD51J19A.

User avatar
RogierWeekers
 
Posts: 6
Joined: Wed Jan 26, 2022 8:43 pm

Re: Bootloader

Post by RogierWeekers »

Thank you however this does not cover the issue. After changing the code for the M0 (see below) it does reboot, but does not get into bootloader mode.


I created this:
a variable
bool Reboot=false;

//in Setup
void SetupWdt() {
// Set up the generic clock (GCLK2) used to clock the watchdog timer at 1.024kHz
REG_GCLK_GENDIV = GCLK_GENDIV_DIV(4) | // Divide the 32.768kHz clock source by divisor 32, where 2^(4 + 1): 32.768kHz/32=1.024kHz
GCLK_GENDIV_ID(2); // Select Generic Clock (GCLK) 2
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

REG_GCLK_GENCTRL = GCLK_GENCTRL_DIVSEL | // Set to divide by 2^(GCLK_GENDIV_DIV(4) + 1)
GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
GCLK_GENCTRL_GENEN | // Enable GCLK2
GCLK_GENCTRL_SRC_OSCULP32K | // Set the clock source to the ultra low power oscillator (OSCULP32K)
GCLK_GENCTRL_ID(2); // Select GCLK2
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

// Feed GCLK2 to WDT (Watchdog Timer)
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK2 to the WDT
GCLK_CLKCTRL_GEN_GCLK2 | // Select GCLK2
GCLK_CLKCTRL_ID_WDT; // Feed the GCLK2 to the WDT
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization

REG_WDT_CONFIG = WDT_CONFIG_PER_1K; // Set the WDT reset timeout to 1 second
while (WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
REG_WDT_CTRL = WDT_CTRL_ENABLE; // Enable the WDT in normal mode
while (WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization

}

in the main loop
if (!WDT->STATUS.bit.SYNCBUSY && Reboot==false) // Check if the WDT registers are synchronized
{
REG_WDT_CLEAR = WDT_CLEAR_CLEAR_KEY; // Clear the watchdog timer
}

User avatar
User_UMjT7KxnxP8YN8
 
Posts: 323
Joined: Tue Jul 17, 2018 1:28 pm

Re: Bootloader

Post by User_UMjT7KxnxP8YN8 »

So, you want it to STAY in the bootloader rather than running the currently-loaded application? Is erasing the current application an option? If so, you could do so in your code, then call this function:

Code: Select all

 *******************************************************************************************************************************************************************************************/
 void reboot(void) {

  //*DBL_TAP_PTR = DBL_TAP_MAGIC;
  //SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;  // force reboot (I had to modify this as shown below for M4)
    __DSB();                                                   // Ensure all outstanding memory accesses included
                                                               //   buffered write are completed before reset 
  SCB->AIRCR  = ((0x5FA << SCB_AIRCR_VECTKEY_Pos)      |
                 (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
                 SCB_AIRCR_SYSRESETREQ_Msk);                   // Keep priority group unchanged
  __DSB();                                                     // Ensure completion of memory access
  while(1);                                                    // wait until reset
  
}   // reboot
If you don't want to erase your app, uncommenting this line may get you the effect you want:

Code: Select all

  //*DBL_TAP_PTR = DBL_TAP_MAGIC;
It's been over a year since I modified the bootloader, so you'll have to look at it to verify my recollection.

User avatar
RogierWeekers
 
Posts: 6
Joined: Wed Jan 26, 2022 8:43 pm

Re: Bootloader

Post by RogierWeekers »

Thanks a lot, but cannot get it to compile, and do not have enough info to correct.
My compiler misses "SCB_AIRCR_PRIGROUP_Msk"
and "DBL_TAP_PTR"
Any suggestions ?

User avatar
User_UMjT7KxnxP8YN8
 
Posts: 323
Joined: Tue Jul 17, 2018 1:28 pm

Re: Bootloader

Post by User_UMjT7KxnxP8YN8 »

I haven't used the M0 but I had to add the register that won't compile in order for it to work on the M4. Perhaps replacing that line with the following will work:

Code: Select all

SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;  // force reboot
You'll have to look at the bootloader for the M0, figure out where DBL_TAP_PTR is located, create a macro defining a pointer to that address and set it to get the desired behavior.

The bootloader source code is at https://github.com/adafruit/uf2-samdx1 in the /src directory.

Locked
Please be positive and constructive with your questions and comments.

Return to “Metro, Metro Express, and Grand Central Boards”