Go Down

Topic: SD card bootloader for WiFi updates ( MKR1000 & FeatherM0 win1500 )  (Read 2234 times) previous topic - next topic


Anybody that DID compile a modified bootloader for SAMD21 might like this  ...

I managed to port the Atmel ASF samd20 SPI bootloader ( SAMD20J18   to the SAMD21G18 )
  - remapped the SPI sercom , the bootpin & the LED
  - Also mapped sercom4 for UART debug

Celebrated  :D after I was able to bootload BLINK sketch stored on my SDcard
       ( compiled on Arduino IDE with modified start address to 0x8000 instead of 0x2000 ).

But :smiley-confuse:  i am stuck not able to run slightly more complex sketches
ex: my main sketch that uses WiFi to download new BIN file.
ex: even the simple ASCIItable dump on the serial port.
they 'did' worked a few 'random' times based on unknown connect/disconnect / reset or else ...
so the process is 99% good BUT i might be missing an Interupt Vector init or something ...

Does anyone know of some limitations in what to DO / DON'T in a bootloader when jumping to the main sketch ?
I think the problem is with reset_handler / Vector table remapping ...

I want to share this bootloader for the greater good of the community
BUT want to clean it first so it would be easier for anyone who may want to contribute.
( i.e : provide easy guidelines for PINs / sercom mapping  of  current and future M0 platforms )

I did manually read the content of Flash 0x8000 and does match the sketch bin file ( content and length )
so the issue may just be with the "switch over"

The bootloader got modified from the Atmel ASF with the samd20_xplained_pro.h
  - proven working solution ( or Atmel wouldn't publish it ... )

What the bootloader does :
- init the Reset_handler
       ( pretty much identical to the one used in the Arduino reset_handler of the bootlooader )
- call main()

  - if bootpin not asserted or memory at addr 0x8000 ( start of sketch ) is 0xFFFF (unprogrammed ) go for bootload_process()

- otherwise, start the sketch: 
    - set MSP to 0x8000    ( sketch start address 0x8000 )
    - set Vector_table to  sketch start_Address
    - jump to sketch startaddress + 4

Using Atmel Studio 7.0 & Segger JLINK

I am currently using the Adafruit M0 winc1500  ( mkr1000 was not available back then ) with SD card interface.


If you are using SPI in your bootloader and then back again in your application, you need to call SPI.end() just before jumping to the application (in your bootloader, before rebasing the stack pointer and all that stuff)

This is more generally true for all Sercom. If you're using Usart in the bootloader, I guess that you have to deactivate it before jumping to the application.


Thanks, sound advice but when I am ready to jump, the CPU is almost clean ...

Once the bootloader is done Flashing, it activates the watchdog and waits...
WDT triggers a reset...

So perfectly clean setup to start with  ...  this is the code



/* Check if WDT is locked */
   if (!(WDT->CTRL.reg & WDT_CTRL_ALWAYSON)) {
      /* Disable the Watchdog module */
      WDT->CTRL.reg &= ~WDT_CTRL_ENABLE;

// Initialize bootpin in input with pull-up ( PB02  is 19 in arduino world )
PORT->Group[1].DIRCLR.reg = (1U << (PIN_PB02 & 0x1F));
PORT->Group[1].OUTSET.reg = (1U << (PIN_PB02 & 0x1F));

// read pin boot pin
volatile bool boot_en;   
boot_en = (PORT->Group[1].IN.reg) & (1U << (PIN_PB02 & 0x1F));

// Check if Flash APP_Start address has been programmed
        app_check_address = APP_START_ADDRESS;
   app_check_address_ptr = (uint32_t *) app_check_address;
   if(*app_check_address_ptr != 0xFFFFFFFF){   // If an app is Loaded ...

          // check if boot pin call for re-flash or the reset was called by WDT
          if ((boot_en) || (PM->RCAUSE.reg & PM_RCAUSE_WDT)) {

              /* Pointer to the Application Section */
         void (*application_code_entry)(void);

              /* Rebase the Stack Pointer */
                 __set_MSP(*(uint32_t *) APP_START_ADDRESS);   

              /* Rebase the vector     table base address */
                 SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
              /* Load the Reset Handler address of the application */
                 application_code_entry = (void (*)(void))    (unsigned *) (*(unsigned *)(APP_START_ADDRESS + 4));                                            

              /* Jump to user Reset Handler in the application */

//  bootloading functions start here ...
// init Clocks , Sercom, SD, etc
// Load file from SD
//  Program flash memory starting at address 0x8000
// activate WDT
// Wait until WDT calls a reset !


OK ! finally fixed my issue ... My bootloader now works like a charm on the feather M0 ( adafruit )

my offer is still valid ... some help on packaging the bootloader in a nice Arduino proof "package" and we'll have a community Web based bootloader.

I'd like to see it run on the Zero and the MKR1000.

Now imagine if codebender would use it too !

looking forward to hear from you all


Hi there
I would love to test your bootloader as my board is designed after the Feather and has an SD card too
Where can I find instructions on how to get this running?



Go Up