This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Switching between two applications using nRF5 SDK

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);
}

Parents Reply Children
No Data
Related