Cortex-M0+ : Can't Jump From Bootloader To App

0

I'm Working on ATSAMC21 (ATSAMC21J18A) with Cortex-M0+, making my CAN bootloader.My IDE is ATMEL studio. Flashing my app is Ok but when I jump in i, it failed.(I tryed with debug and without) In dissaseembly it point to the first of these two line:

*FFFFFFFE ?? ??                ???      Memory out of bounds or read error*

*00000000 a0.32                 adds    r2, #160*   

pc disassembly point

My bootloader space in my linker :

MEMORY
{
  rom      (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00008000 
  ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 
}

My application (or firmware) space in my linker :

MEMORY
{
  rom      (rx)  : ORIGIN = 0x00010000, LENGTH = 0x00030000 
  ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 
}

Before jumping,

I disabled irq interrupt, defined my entry point and my stack pointer, and change VTOR. Here is my code to jump:

void JumpToApp(void) {

uint16_t i;
uint32_t startAddress, applicationStack;


/* Check if WDT is locked */

if (!(WDT->CTRLA.reg & WDT_CTRLA_ALWAYSON)) {

    /* Disable the Watchdog module */

    WDT->CTRLA.reg &= ~WDT_CTRLA_ENABLE;

}
    //stop general IT
    __disable_irq();

    // Disable SysTick
    SysTick->CTRL = 0;

    // Disable IRQs & clear pending IRQs
    for (i = 0; i < 8; i++) {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }

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

    startAddress = FLASH_APP_VADRESS; //HERE 0x00010000, my start App

    applicationStack = (uint32_t) *(volatile unsigned int*) (startAddress);

    application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(FLASH_APP_VADRESS + 4)); //HERE 0x00010004

    // Rebase the Stack Pointer 
    __DSB();
    __ISB();    
    __set_MSP(*(uint32_t *)applicationStack); //HERE 0x00010000, my start App

    // Rebase the vector table base address 
    SCB->VTOR = ((uint32_t)startAddress & SCB_VTOR_TBLOFF_Msk);
    __DSB();
    __ISB();


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

I tried to add +1 at my application_code_entry , like a odd Thumb mode, i see this for Cortex-M3 but it don't work, fail in general IT.

Then I rename main() by main_boot() and Reset_Handler() by Reset_Handler_Boot() (and by changing in propety flag linker the --entry=Reset_Handler_Boot)

But still not jumping.

I don't know what i'm doing bad.May be there is a long jump to do? Split the RAM? If somebody have an idea?

Thank You!!!!!!!!!!!!!!!!!!!


Thank you, (it was a mistake :) )but this hard fault doesn't resolve my jump (in fact i Used directly the adress __set_MSP(*(uint32_t *)(FLASH_APP_VADRESS));

My MSP is not 0x0000000, it's 0x20003240 so is it an offset to apply to my new MSP? (see the picture linked)

Here is my code for testing the MSP

ReadMsp=__get_MSP(); //result 0x20003240, before change it
__DSB();
__ISB();    
__set_MSP(*(uint32_t *)applicationStack);


// Rebase the vector table base address TODO: use RAM 
SCB->VTOR = ((uint32_t)startAddress & SCB_VTOR_TBLOFF_Msk);
__DSB();
__ISB();

ReadMsp=__get_MSP(); //result is 0xFFFFFFFC , why ???
    __DSB();
    __ISB();
__set_MSP(0x00010000);
    __DSB();
    __ISB();
ReadMsp=__get_MSP(); //result is 0x00010000, better than my same #define FLASH_APP_VADRESS or *(uint32_t *)applicationStack in __MSP
//applicationEntry();
// Load the Reset Handler address of the application 

//application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)(FLASH_APP_VADRESS ));
// Jump to user Reset Handler in the application 
application_code_entry();

Should I use (0x20003240 + 0x00010000) for my new MSP?

enter image description here

vector
bootloader
cortex-m
asked on Stack Overflow Apr 4, 2018 by TM_embbeded • edited Apr 25, 2019 by artless noise

2 Answers

1

You are dereferencing the SP stack pointer twice:

applicationStack = (uint32_t) *(volatile unsigned int*) (startAddress);
// ...                      --^
 __set_MSP(*(uint32_t *)applicationStack);
//        -^

You need to do that only once. The second time sets SP highly likely to zero, resulting to a fault once the stack is used.

answered on Stack Overflow Apr 4, 2018 by Turbo J
0

I found the answer !!!

Finally to jump, just like atmel say BUT before I needed to uninitialized some module.

So : ATMEL part :

*// Pointer to the Application Section 
void (*application_code_entry)(void);
// Rebase the Stack Pointer 
__set_MSP(*(uint32_t *)FLASH_APP_VADRESS);
// Rebase the vector table base address TODO: use RAM 
SCB->VTOR = ((uint32_t)FLASH_APP_VADRESS & SCB_VTOR_TBLOFF_Msk);
// Load the Reset Handler address of the application 
application_code_entry = (void (*)(void))(unsigned *)(*(unsigned *)
(FLASH_APP_VADRESS + 4));
// Jump to user Reset Handler in the application 
application_code_entry();*

My part before executing this :

*Flash_Deinit(); //flash uninit
config_TC_Deinit(); //time clock uninit, scheduler
can_deinit0(); // module CAN0
can_deinit1(); // module CAN1
Handle_Wdt_Disable();
__disable_irq();



// Disable SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;

// Disable IRQs & clear pending IRQs
for (i = 0; i < 8; i++) {
    NVIC->IP[i] = 0x00000000;
}
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICPR[0] = 0xFFFFFFFF;*

I hope it will help someone !!! :)

answered on Stack Overflow Jun 13, 2018 by TM_embbeded

User contributions licensed under CC BY-SA 3.0