Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Can't jump to a custom app location using nrf_bootloader_app_start with SDK V15

With SDK V14.2, I was able to specify internal flash address argument into nrf_bootloader_app_start(uint32_t start_addr) and was able to boot into the address. With SDK V15, the argument option is removed and the jump address is fixed to MBR_SIZE within the nrf_bootloader_app_start(void) function. I tried modifying the start address within nrf_bootloader_app_start but I was not able to boot into the custom app location.

Parents
  • Note that 's solution doesn't work if there is no SoftDevice present.

    The reason it was removed was that in SDK 15, we also support having no SoftDevice present, so this function would have needed to accomodate that new configuration. Removing the start address argument allowed us to not implement something we didn't need for our own examples.

    The DFU we provide only allows placing apps 1) at 0x1000 (after the 'MBR'), or 2) after the SoftDevice if there is a SoftDevice present. The start address in both cases can be 0x1000, so we hard-coded it.

    Implementing this functionality for the general case is surprisingly tedious and has tricky caveats, but if you know what you need for your specific case, it's quite doable.

    Below is an untested mockup. Use _with_sd if the app needs the SD, and likewise, use _without_sd if the app doesn't need the SD. This might not compile out of the box (because of dependencies), and might not run together with old MBRs. Note that I changed the app_start_impl call to use app_start_final from SDK 15 instead. It should do the same thing, and also give you the memory protection present in 15. Note also that using the _with_sd call in otherwise SD-independent bootloaders (i.e. UART or USB) makes them SD-dependent and brickable by an update that removes the SD. Add the BLE_STACK_SUPPORT_REQD define to prevent this.

    void start_app_with_sd(cb_uint32 startAddress)
    {
        nrf_dfu_mbr_init_sd();
    
        // Disable and clear interrupts
        NVIC->ICER[0] = 0xFFFFFFFF;
        NVIC->ICPR[0] = 0xFFFFFFFF;
        NVIC->ICER[1] = 0xFFFFFFFF;
        NVIC->ICPR[1] = 0xFFFFFFFF;
    
        sd_softdevice_vector_table_base_set(startAddress);
        nrf_dfu_mbr_irq_forward_address_set(MBR_SIZE);
        nrf_bootloader_app_start_final(startAddress);
    }
    
    void start_app_without_sd(cb_uint32 startAddress)
    {
        NVIC->ICER[0] = 0xFFFFFFFF;
        NVIC->ICPR[0] = 0xFFFFFFFF;
        NVIC->ICER[1] = 0xFFFFFFFF;
        NVIC->ICPR[1] = 0xFFFFFFFF;
    
        nrf_dfu_mbr_irq_forward_address_set(startAddress);
        nrf_bootloader_app_start_final(startAddress);
    }
    
    // nrf_dfu_mbr.c:
    // Replace this
    uint32_t nrf_dfu_mbr_irq_forward_address_set(void)
    {
        uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
        uint32_t address = MBR_SIZE;
        ...
        
    // With this
    uint32_t nrf_dfu_mbr_irq_forward_address_set(uint32_t address)
    {
        uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
        ...

Reply
  • Note that 's solution doesn't work if there is no SoftDevice present.

    The reason it was removed was that in SDK 15, we also support having no SoftDevice present, so this function would have needed to accomodate that new configuration. Removing the start address argument allowed us to not implement something we didn't need for our own examples.

    The DFU we provide only allows placing apps 1) at 0x1000 (after the 'MBR'), or 2) after the SoftDevice if there is a SoftDevice present. The start address in both cases can be 0x1000, so we hard-coded it.

    Implementing this functionality for the general case is surprisingly tedious and has tricky caveats, but if you know what you need for your specific case, it's quite doable.

    Below is an untested mockup. Use _with_sd if the app needs the SD, and likewise, use _without_sd if the app doesn't need the SD. This might not compile out of the box (because of dependencies), and might not run together with old MBRs. Note that I changed the app_start_impl call to use app_start_final from SDK 15 instead. It should do the same thing, and also give you the memory protection present in 15. Note also that using the _with_sd call in otherwise SD-independent bootloaders (i.e. UART or USB) makes them SD-dependent and brickable by an update that removes the SD. Add the BLE_STACK_SUPPORT_REQD define to prevent this.

    void start_app_with_sd(cb_uint32 startAddress)
    {
        nrf_dfu_mbr_init_sd();
    
        // Disable and clear interrupts
        NVIC->ICER[0] = 0xFFFFFFFF;
        NVIC->ICPR[0] = 0xFFFFFFFF;
        NVIC->ICER[1] = 0xFFFFFFFF;
        NVIC->ICPR[1] = 0xFFFFFFFF;
    
        sd_softdevice_vector_table_base_set(startAddress);
        nrf_dfu_mbr_irq_forward_address_set(MBR_SIZE);
        nrf_bootloader_app_start_final(startAddress);
    }
    
    void start_app_without_sd(cb_uint32 startAddress)
    {
        NVIC->ICER[0] = 0xFFFFFFFF;
        NVIC->ICPR[0] = 0xFFFFFFFF;
        NVIC->ICER[1] = 0xFFFFFFFF;
        NVIC->ICPR[1] = 0xFFFFFFFF;
    
        nrf_dfu_mbr_irq_forward_address_set(startAddress);
        nrf_bootloader_app_start_final(startAddress);
    }
    
    // nrf_dfu_mbr.c:
    // Replace this
    uint32_t nrf_dfu_mbr_irq_forward_address_set(void)
    {
        uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
        uint32_t address = MBR_SIZE;
        ...
        
    // With this
    uint32_t nrf_dfu_mbr_irq_forward_address_set(uint32_t address)
    {
        uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
        ...

Children
No Data
Related