This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

FOTA Upgrade from SDK 15.2 to 17.0

Hi,

We have a working application that allows FOTA when using the SDK 15.2 bootloader.
We have recently tried to migrate this to SDK 17.0, and everything works except for the FOTA capabilities. 

The ability to receive and process the new firmware still works, but the bootloader is not working properly.
Whenever we try to restart the application so the bootloader can flash the new image, nothing happens.
The device enters a reset loop where the application detects a valid cached image and resets the device for the bootloader to flash it. 

A sanitised snippet of the FOTA code handling the update of the BL settings is as follows:

new_settings = *(nrf_dfu_settings_t *)(&__BlSettingsStart);
new_settings.bank_1.image_crc = fota_upgrade.crc;
new_settings.bank_1.image_size = fota_get_image_size(FOTA_FW_SLOT_ID);
new_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_APP;
new_settings.progress.update_start_address = (uint32_t)&__SwapStart + FOTA_HEADER_SIZE;
new_settings.crc = calc_settings_crc(&new_settings);

flash_is_busy = true;
sd_flash_page_erase(((uint32_t)&__BlSettingsStart) >> 12);
yield(!flash_is_busy);

log("Settings page erased");

flash_is_busy = true;
num_words = (sizeof(new_settings) + 3) / sizeof(uint32_t);
sd_flash_write((uint32_t *)&__BlSettingsStart, (uint32_t *)&new_settings, num_words);
yield(!flash_is_busy);

log("New settings written");


This code was working with the 15.2 bootloader.
Now, the bootloader executes, but the new firmware is not loaded. The output from debugging the bootloader is:

<info> app: Inside main
<debug> app: In nrf_bootloader_init
<debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
<debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
<debug> nrf_dfu_settings: Using settings page.
<debug> nrf_dfu_settings: Copying forbidden parts from backup page.
<debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
<info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
<debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
<debug> app: Enter nrf_bootloader_fw_activate
<info> app: No firmware to activate.
<debug> app: App is valid
<info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
<debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
<debug> app: Running nrf_bootloader_app_start with address: 0x00001000
<debug> app: Disabling interrupts. NVIC->ICER[0]: 0x0

We have defined NRF_BL_DFU_ALLOW_UPDATE_FROM_APP, but I think this should be causing the postvalidation routine to execute.
I have tried adding the following to the FOTA routine:

new_settings.bank_current = NRF_DFU_CURRENT_BANK_1;

but it only causes the postvalidate routine to run and skip immediately as no command is present.
Should I be configuring something else for the bootloader to pick up the new image?

Any help will be much appreciated.
Best wishes,
Alberto
 

Parents
  • Hi Alberto, 

    Could you give some more information about your bootloader ? I assume you have done some modification to the bootloader ? and you are porting the bootloader in SDK v15.2 to SDK v17.0 instead of modifying the bootloader in SDK v17.0 ? 

    Have you tried to step into the nrf_bootloader_fw_activate() function and check why it doesn't activate the app ? 
    I don't think turning on NRF_BL_DFU_ALLOW_UPDATE_FROM_APP would be correct here. This option is used to enable receiving image by the app and then only activate image using the bootloader. 

  • Hi Hung,

    Thanks for getting back to me.

    We are, in fact, receiving the new firmware image from the application. The FOTA snippet I included is from a part of our application. We run a mesh OS that allows distributing the firmware update image to the nodes of the network and stores it in flash memory (writing from __SwapStart).

    As far as I'm aware, we ran an unmodified SDK v15.2 bootloader and are now using an unmodified SDK v17.0 bootloader.
    I will confirm this shortly.

    As for why does the bootloader don't activate the app, when the postvalidate routine is executed, there is no command stored, and it reverts to the old image.

    Best wishes
    Alberto

Reply
  • Hi Hung,

    Thanks for getting back to me.

    We are, in fact, receiving the new firmware image from the application. The FOTA snippet I included is from a part of our application. We run a mesh OS that allows distributing the firmware update image to the nodes of the network and stores it in flash memory (writing from __SwapStart).

    As far as I'm aware, we ran an unmodified SDK v15.2 bootloader and are now using an unmodified SDK v17.0 bootloader.
    I will confirm this shortly.

    As for why does the bootloader don't activate the app, when the postvalidate routine is executed, there is no command stored, and it reverts to the old image.

    Best wishes
    Alberto

Children
  • Thanks for clarification. 

    Have you checked after your app switch to the bootloader the bootloader setting has been written correctly ? 
    I think it can be solved easily by stepping into the bootloader code or printing out the log and check why the bootloader doesn't activate the app. 

    Most likely it's the bootloader setting was not written correctly. 

  • Hi Hung,

    Thanks for the guidance.
    I've finally found this related thread useful: https://devzone.nordicsemi.com/f/nordic-q-a/69006/custom-dfu-process

    Give we are directly writing to bank_1 the information of the upgrade image, I had to update the nrf_dfu_settings.c file with:

    static void settings_forbidden_parts_copy_from_backup(uint8_t * p_dst_addr)
    {
    #if NRF_DFU_IN_APP || NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
        REGION_COPY_BY_MEMBER(settings_version, bank_current, p_dst_addr);
        REGION_COPY_BY_MEMBER(bank_0, bank_1, p_dst_addr);
        REGION_COPY_BY_MEMBER(sd_size, progress, p_dst_addr);
        REGION_COPY_BY_MEMBER(boot_validation_crc, peer_data, p_dst_addr);
    #else
        REGION_COPY_BY_MEMBER(settings_version, enter_buttonless_dfu, p_dst_addr);
        REGION_COPY_BY_MEMBER(init_command, peer_data, p_dst_addr);
    #endif
    }

    REGION_COPY_BY_MEMBER(bank_0, write_offset, p_dst_addr); is the standard SDK file.

    Best wishes,
    Alberto

Related