SAMD21 Bootloader PingPong

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am facing a problem, my application should allow to receive an update over the i2c interface.

I have devided the Flash memory into 2 equal parts, if the code is running from the lower part, it should save the new hex file to the upper flash part, and if the current application is running in the high part of the flash memory, it should save the new firmware in the lower part.

This is all working fine.

 

But now i don't know how to go further.

 

the complete hex file is lets say programmed in flash memory at the address 0x00020000

 

First of all i am rebasing the stackpointer back to the initial value so the complete stack is available again.

Second i am rebasing the vector table, but i don't know if that is correct. 

Then i am fetching the entry point for the code to start running (can be found in the Vector table with an offset of +4 according to 

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BABIFJFG.html

 

This value should have an offset with the address i have put the code in (in my case being 0x00020000)

 

and then i try jumping to this address. below code shows how i am doing that.

 

This is not working. i am missing some knowledge i think.

 

Could someone explain me what the correct way is to tackle my problem?

 

 

    void (*application_code_entry)(void);

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

    /* Rebase the vector table base address */
    SCB->VTOR = ((uint32_t) application_address & SCB_VTOR_TBLOFF_Msk);

    /* Load the Reset Handler address of the application */
    application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)
    (application_address + 4));

    application_code_entry += application_address;

    /* Jump to user Reset Handler in the application */
    application_code_entry();

This topic has a solution.
Last Edited: Fri. Jan 11, 2019 - 02:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the new app at 0x00020000 is actually built to reside at address 0 then there is no hope of that working because the relocation you do here

application_code_entry += application_address;

would have to be done for every absolute address in the app. To avoid that you could have a boot loader move the whole new app to low address  (after the boot loader). The boot loader could also swap the new and old app (to allow the update to be undone). Not completely trivial to have that reliable. I would prefer a regular boot loader that also does the i2c download (then you don't need space for 2 apps and always have the update code in place).

 

But if the new app is built to execute at 0x00020000 then the relocation is not needed at all (just remove that one line).

/Lars

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars,

 

Ok this was exactly what i was affraid of, that all the addresses would have to be remapped. but that is not really possible to interprete this.

So i tried doing what you described.

I updated the linker script for the program to reside on a certain location.

 

i Changed this in samd21j18a_flash.ld

 

/*  rom      (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00040000 */    
  rom      (rx)  : ORIGIN = 0x0000C800, LENGTH = 0x00033800
 

in my bootloader i am now storing the file to this address 0x0000C800

 

 

with this code running now, it still won't boot up the new application :(

 

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

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

    /* Rebase the vector table base address */
    SCB->VTOR = ((uint32_t) application_address & SCB_VTOR_TBLOFF_Msk);

    /* Load the Reset Handler address of the application */
    application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)
    (application_address + 4));

    /* application_code_entry += application_address; */

    /* Jump to user Reset Handler in the application */
    application_code_entry();

 

I Debugged and the data is valid and in the correct flash memory address. What am i doing wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know, that looks 100% like what I have in my boot loader. Could it be a problem with the app startup, i.e., did you try this with a really simple app (like blinking a led)? Do you perform a reset before executing the app start or is this just after code has been downloaded and flashed? It can make a difference if the app can't tolerate that some peripherals are initialized already.

/Lars

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars,

 

I enabled the watchdog, and now i am indeed first resetting the device, and then immediatly jumping to that address. this is working fine.

 

so the clue is

1. Bootloader @ address 0x00000000

2. Do whatever is needed to save the incoming program to a certain address, (i 've used 0x0000C800

3. The actual program needs to be built with the linker file pointing at that address 0x0000C800 (with size as much smaller)

4. IMPORTANT, first reset the device, and as short as possible, jump to the program entry address that is found in the Vector table start address + 4 (being 0x0000C804)

5. Clap in your hands its working.

 

thx a lot Lars for the Help. but indeed the reset did the trick probably like you said... some devices should not be initialized when jumping to the entry point of a program.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Team,

 

I have written the Bootloader for the ATSAMD21J18A Controller via UART.

I am using Atmelstudio version7 IDE for building the boot loader and application

 

To jump to application, I have used the following code:

 

Boot section is 

  rom      (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00007800

 

Application section is 

rom      (rx)  : ORIGIN = 0x0000C800, LENGTH = 0x00033600

 

There is gap between Boot loader section and application section:

 

to jump to application following code is used

 

--------------------------------------------------------------------------------------------

        __set_MSP(*(uint32_t *)APP_START_ADDRESS);

    

      app_check_address = (uint32_t)APP_START_ADDRESS;

    

     /* Re base the vector table base address TODO: use RAM */

    SCB->VTOR = (app_check_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 */

        application_code_entry();

 

-----------------------------------------------------------------------------------------------------

 

 

when we flash the application:

 

I found that application is not starting from 0x0000C800

It is starting from (0x0000C800 +8)

 

I am attaching the section of the flash read via debugger:   what could be the reason for this?                                                                                                            

 

 

 

I am using UART Interrupt in bootloader. same UART interrupt is also required in the Application.

is relocate the vector table is good enough?

do we need to consider anything else.?  Kindly suggest.

 

Regards

Kumar