There is a previous similar question here:
https://devzone.nordicsemi.com/f/nordic-q-a/16382/switching-between-apps-with-dual-bank
I am using nRF5232, nRF5 SDK v16.0.0, and using the latest SEGGER Embedded Studio. Both applications use SoftDevice. (If it matters, both use FreeRTOS)
I'm wanting to do the same thing as stated in the previous questions, but I'm looking for two examples that can be built with SES.
My Application1 is located at 0x26000 and my Application2 is located at 0x40000.
According to my .hex files, my Applications are being placed at the correct addresses, however when I try to jump to them, I get some sort of fault.
I tried using code the following code I took from nrf_bootloader, and I'm getting stuck in the HardFault_Handler:
/**@brief Function that sets the stack pointer and link register, and starts executing a particular address. * * @param[in] new_msp The new value to set in the main stack pointer. * @param[in] new_lr The new value to set in the link register. * @param[in] addr The address to execute. */ #if defined ( __CC_ARM ) __ASM __STATIC_INLINE void jump_to_addr(uint32_t new_msp, uint32_t new_lr, uint32_t addr) { MSR MSP, R0; MOV LR, R1; BX R2; } #else __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)); } #endif /**@brief Function for booting an app as if the chip was reset. * * @param[in] vector_table_addr The address of the app's vector table. */ __STATIC_INLINE void app_start(uint32_t vector_table_addr) { const uint32_t current_isr_num = (__get_IPSR() & IPSR_ISR_Msk); const uint32_t new_msp = *((uint32_t *)(vector_table_addr)); // The app's Stack Pointer is found as the first word of the vector table. const uint32_t reset_handler = *((uint32_t *)(vector_table_addr + sizeof(uint32_t))); // The app's Reset Handler is found as the second word of the vector table. const uint32_t new_lr = 0xFFFFFFFF; __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. ASSERT(current_isr_num == 0); // If this is triggered, the CPU is currently in an interrupt. // The CPU is in Thread mode (main context). jump_to_addr(new_msp, new_lr, reset_handler); // Jump directly to the App's Reset Handler. } static void application2_start(void) { // Disable interrupts NVIC->ICER[0]=0xFFFFFFFF; NVIC->ICPR[0]=0xFFFFFFFF; #if defined(__NRF_NVIC_ISER_COUNT) && __NRF_NVIC_ISER_COUNT == 2 NVIC->ICER[1]=0xFFFFFFFF; NVIC->ICPR[1]=0xFFFFFFFF; #endif app_start(0x40000); }