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.

  • 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

  • Hi, 

    Thanks for your detailed explanation. 

    I'm using nRF5 SDK for Thread and Zigbee v4.0.0 which uses SDK 16.0 

    I doubt that there is something wrong with the way I'm debugging the boot loader. 

    In a working case - where DFU completes successfully and a new image boots. After successful completion of DFU image transfer, DFU client node is reset. After Node reset  - I don't see any boot loader logs. I've to exit from JlinkExe process and reconnect with the device to get logs again. Now if I wait for sufficient amount of time - around 30 seconds, I get logs from new image. 

    If I don't wait for 30 seconds and immediately exit from JlinkExe process and connect with the device - I get boot loader logs but device firmware is not updated. I'm attaching logs for this case. By looking at logs - can you make sense of what's going wrong ? 

    <info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_CONTINUE
    <info> COAP_DFU: Requesting [f] (block:3762 mid:61189)
    <info> background_dfu: Storing block (b:3762 c:3762).
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000E5900, src=0x200093B0, len=92 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000E5900, pending 0
    <info> nrf_dfu_validation: Hash verification. start address: 0x70000, size: 0x7595C
    <info> nrf_dfu_validation: result of Hash Verification 1 
    <info> nrf_dfu_validation: Control is here .....is_trusted 0 ret_val : 1
    <info> nrf_dfu_validation: setting current Bank to 1
    <info> nrf_dfu_req_handler: res.result : 1
    <info> nrf_dfu_req_handler: After -- res.result : 1
    <info> background_dfu: 
    background dfu handle event
    
    <info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_COMPLETE
    <info> background_dfu: 
    background dfu handle event : background dfu download firmware
    
    <info> nrf_dfu_settings: crc : 52A322F8,bank_c<info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 p<info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20006C78, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> COAP_DFU: Reset after DFU
    
    ###RTT Client: Connection lost. Going to reconnect.
    ###RTT Client: Connecting to J-Link RTT Server via localhost:19021 .....
    ###RTT Client: Connected.
    
    SEGGER J-Link V6.62d - Real time terminal output
    J-Link OB-SAM3U128-V2-NordicSemi compiled Mar 17 2020 14:43:00 V1.0, SN=683670592
    Process: JLinkExe
    <info> app: Inside main
    
    <info> nrf_dfu_settings: settings_valid : 1 settings_backup_valid : 1
    <info> nrf_dfu_settings: crc : F8 22 A3 52
    <info> nrf_dfu_settings: Returning from reinit - bank_current : 1,crc : 52A322F8
    <info> nrf_dfu_settings: crc : 52A322F8,bank_current : 1
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=ing 0
    ing 0
    e.
    <info> nrf_dfu_flash: Flash erase success: addr=0x00041000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00041000, src=0x000B0000, len=32768 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00041000, pending 0
    <info> nrf_dfu_settings: crc : A8E5F317,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00049000, len=8 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x00049000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00049000, src=0x000B8000, len=32768 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00049000, pending 0
    <info> nrf_dfu_settings: crc : 5940B58E,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00051000, len=8 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x00051000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00051000, src=0x000C0000, len=32768 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00051000, pending 0
    <info> nrf_dfu_settings: crc : 9DC77F9,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00059000, len=8 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x00059000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00059000, src=0x000C8000, len=32768 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00059000, pending 0
    <info> nrf_dfu_settings: crc : 617B3EFD,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00061000, len=8 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x00061000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00061000, src=0x000D0000, len=32768 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00061000, pending 0
    <info> nrf_dfu_settings: crc : 31E7FC8A,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00069000, len=8 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x00069000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00069000, src=0x000D8000, len=32768 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00069000, pending 0
    <info> nrf_dfu_settings: crc : C042BA13,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00071000, len=6 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x00071000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x00071000, src=0x000E0000, len=22876 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x00071000, pending 0
    <info> nrf_dfu_settings: crc : DA92FEEA,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_settings: crc : 5DCA91E4,bank_current : 0
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20001020, len=896 bytes), queue usage: 1
    <info> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <info> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <info> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <info> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20000CA0, len=896 bytes), queue usage: 1
    <info> app: Inside main
    
    <info> nrf_dfu_settings: settings_valid : 1 settings_backup_valid : 1
    <info> nrf_dfu_settings: crc : E4 91 CA 5D
    <info> nrf_dfu_settings: Returning from reinit - bank_current : 0,crc : 5DCA91E4
    <info> nrf_dfu_settings: crc : 5DCA91E4,bank_current : 0
    <info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <info> nrf_dfu_settings:  err_code : 0
    <info> app: ret_val 0 of nrf_dfu_settings_init
    <info> app:  s_dfu_settings.bank_current : 0
    <info> app: No firmware to activate.
    
    

    Exiting immediately and reconnecting with the device is the only way to get boot loader logs. 

     

  • 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.

  • Hi ashish!

    I'm facing the same issue, but I can't achieve this:

    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().

    I did the same updates:

    in on_data_obj_write_request():

    in on_data_obj_create_request():

    but I have my code stucked after the first write operation:

    Can you give me any tips about your solution?

    Thanks,

    Alessio

Related