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

Dual Bank DFU with external qspi flash over Thread

Hello Everyone, 

We are using nRF52840 IC for our products which has 1 MB of flash.   

Thread Secure DFU Example provided with Nordic SDK supports only Dual Bank DFU. This limits the application size.  

Our Application size is increasing and therefore Dual Bank DFU cannot accommodate new application image. 

To resolve this issue, we have decided to add an external Flash which can act as Bank1 for storing DFU image.  

We have successfully directed incoming DFU packets to external QSPI flash by modifying nrf_dfu_flash_erase to qspi_earse in on_data_obj_create_request() and nrf_dfu_flash_store to QSPI store in on_data_obj_write_request().

During post validation - we have read entire firmware from external flash for Hash Verification. 

After that, by enabling logs, I  can see bootloader settings are updated. Here, 3 parameters with DFU Banks 

typedef struct
{
uint32_t image_size; /**< Size of the image in the bank. */
uint32_t image_crc; /**< CRC of the image. If set to 0, the CRC is ignored. */
uint32_t bank_code; /**< Identifier code for the bank. */
} nrf_dfu_bank_t; 

For Bank0, these members remain intact and for Bank1 - they remain 0.  And bank_current of nrf_dfu_settings_t structure is changed to 1. I can see flash write success logs. 

But After, booting - bootloader settings are reverted back. i.e. bank_current is changed to 0 and crc of settings page is also reverted back to before dfu.  

Consequently, this part of bootloader 

#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP
// Postvalidate if DFU has signaled that update is ready.
if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1)
{
postvalidate();
}
#endif

is never executed. 

Can someone please point it out which part of boot loader might be doing that ?  

Thanks.

Parents
  • Hi,

    Which SDK version are you using?

    If you are using the latest version, the Thread DFU Client application is not allowed to modify the bank_0 and bank_1 members in nrf_dfu_settings_t. These members will be copied from the Bootloader settings backup page by the following function:

    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, write_offset, 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
    }

    In order for the Thread DFU client to notify to the bootloader that there is a new firmware available, it writes the bank_current member (this happens in postvalidate() function in client):

    if (!is_trusted)
    {
        if (ret_val == NRF_DFU_RES_CODE_SUCCESS)
        {
            s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1;
        }
        else
        {
            nrf_dfu_settings_progress_reset();
        }
    }

    If the settings page is not valid (invalid CRC), the backup page will be restored. Are you able to debug the bootloader and see where it runs inside nrf_dfu_settings_reinit()?

    Best regards,
    Jørgen

  • I'm a bit confused by the log. It looks like it is copying the new firmware, is this not the case?

    There seems to be some glitching or missing logs around line 41-42, so it is a bit hard to see exactly what happens. Disabling logging in the application should help you get all logs from bootloader. You may also configure the RTT to ble blocking if buffer is full, to make sure you get all logs.

Reply Children
No Data
Related