Unlike other ARM controllers that directly jump to address 0 at reset, the Cortex-M series takes the start address from a vector table. If the program is loaded directly (without a bootloader), the vector table is at the start of the binary (loaded or mapped to address 0). First entry at offset 0 is the initial value of the stack pointer, second entry at address 4 is called the reset vector, it contains the address of the first instruction to be executed.
Programs loaded with a bootloader usually preserve this arrangement, and put the vector table at the start of the binary, 0x08008000
in your case. Then the reset vector would be at 0x08008004
. But it's your application, you should check where did you put your vector table. Hint: look at the .map
file generated by the linker to be sure. If it's indeed at 0x08008000
, then you can transfer control to the application reset vector so:
void (*app)(void); // declare a pointer to a function
app = *(void (**)(void))0x08008004; // see below
app(); // invoke the function through the pointer
The complicated cast in the second line converts the physical address to a pointer to a pointer to a function, takes the value pointed to it, which is now a pointer to a function, and assigns it to app
.
Then you should manage the switchover to the application vector table. You can do it either in the bootloader or in the application, or divide the steps between them.
- Disable all interrupts and stop SysTick. Note that SysTick is not an interrupt, don't call
NVIC_DisableIRQ()
on it. I'd do this step in the bootloader, so it gets responsible to disable whatever it has enabled.
- Assign the new vector table address to
SCB->VTOR
. Beware that the boilerplate SystemInit()
function in system_stm32l1xx.c
unconditionally changes SCB->VTOR
back to the start of the flash, i.e. to 0x08000000
, you should edit it to use the proper offset.
You can load the stack pointer value from the vector table too, but it's tricky to do it properly, and not really necessary, the application can just continue to use the stack that was set up in the bootloader. Just check it to make sure it's reasonable.