I'm writing my own lightweight bootloader for nRF5340 (which may or may not turn out to be a good idea). I have something similar that I'm using successfully on nRF52832 based on a minimal Zephyr application.
The bootloader doesn't use TF-M so it has a single flash partition, however the application has both secure and non-secure code. By inspection the vector table is in the non-secure partition.
This is what I do in the bootloader to start up the application:
__STATIC_INLINE void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr) { __ASM volatile("MSR MSP, %[arg]" : : [arg] "r" (new_msp)); __ASM volatile("MOV LR, %[arg]" : : [arg] "r" (new_lr) : "lr"); __ASM volatile("BX %[arg]" : : [arg] "r" (addr)); } __STATIC_INLINE void app_start(uint32_t vector_table_addr) { struct arm_vector_table *vt = (void *)vector_table_addr; printk("Inspect vector table at %08x\n", vector_table_addr); //const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk); const uint32_t new_msp = vt->msp; // The app's Stack Pointer is found as the first word of the vector table. const uint32_t reset_handler = vt->reset; // The app's Reset Handler is found as the second word of the vector table. const uint32_t new_lr = 0xFFFFFFFF; printk("Stack pointer %08x\n", new_msp); printk("Reset vector %08x\n", reset_handler); irq_lock(); __set_CONTROL(0x00000000); // Set CONTROL to its reset value 0. __set_PRIMASK(0x00000000); // Set PRIMASK to its reset value 0. __set_BASEPRI(0x00000000); // Set BASEPRI to its reset value 0. __set_FAULTMASK(0x00000000); // Set FAULTMASK to its reset value 0. jump_to_addr(new_msp, new_lr, reset_handler); // Jump directly to the App's Reset Handler. }
I'm investigating this by programming the bootloader code first and then running a debug session with the application code. I can see from the RTT output that the bootloader starts up and attempts to run the application, but it doesn't hit a breakpoint in the application's Reset_Handler(); instead it seems to jump immediately into k_sys_fatal_error_handler with reason 25.
Debugging the bootloader code I see that jump_to_addr appears to have the correct parameters, and switching to disassembly mode I see that the application's Reset_Handler() is invoked and at least the first few instructions are executed.
Can you see what I'm going wrong?