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

DFU with external QSPI memory

Hi,

   I am working on project, in which we using nordic nRF52840 chip. We need to flash the app+SD+BL image file in external QSPI memory.

After prevalidation, the DFU controller starts to send flash image package, we need to receive this and need to save in external QSPI memory. Once the postvalidation is successful, then read all the flash image package stored in external QSPI memory and write it to internal flash memory.

For that we use secure bootloader example code as reference file. I need to know where i need to modify the secure bootloader code.

I noticed that after prevalidation, the flash is erased in on_data_obj_create_request() function in nrf_dfu_req_handler.c file, and flash is written in on_data_obj_write_request() under the same c file. Is that right?

Thanks & Regards

Mohammad Gouse

  • @Mohammad, the Hex file line you're referencing is only 14 bytes of data.  Consequently the next two bytes of QSPI flash are not written and hence are 0xff in value.  The hash calculation may be assuming that the extra two bytes are padded with zeroes to make it a full word write (to Flash Memory).

    From what I've seen with the BLE data transfers to the DFU code, all data blocks have always been full word multiples so I'm not sure how the raw Hex data would appear on the DFU end of the transfer.

  • Hi TomWS

    Actually i have problem in reading QSPI data for hash calculation. I have decalred a array 

    uint8_t m_buffer_rx[CODE_PAGE_SIZE];

    In which reading data from QSPI  read,

    NRF_LOG_DEBUG("Reading buffer at address = 0x%x with size = 0x%x", src_addr, bytes);
    nrf_dfu_qspi_read(src_addr, &m_buffer_rx, ALIGN_NUM(sizeof(uint32_t), bytes));

    Error is thrown after the nrf_dfu_qspi_read is called,

    <info> nrf_dfu_validation: Hash verification. start address: 0x5000, size: 0x6AC
    <debug> nrf_dfu_qspi: nrf_qspistorage_read(addr=0x5000, src=0x200084FD, len=1708 bytes), queue usage: 1
    <error> app: Received a fault! id: 0x00004002, pc: 0x00000000, info: 0x2003FD80


    NRFX_ASSERT(nrfx_is_word_aligned(p_rx_buffer)) is thrown error because address of m_buffer_rx = 0x200084FD.

    ((((uint32_t)p_object) & 0x3u) == 0u);  ==> 1

    How to solve this issue??

  • I find it odd (no pun intended) that the buffer isn't aligned on a 32bit boundary, but the modifier __ALIGN(4) can be used to force it on a 4 byte boundary as in:

    __ALIGN(4) uint8_t m_buffer_rx[CODE_PAGE_SIZE];

  • Hi TomWS,

    Thanks for your response.

    Hash test is passed. But still the blinky_pca10056_mbr.hex is not written into flash memory because the image_copy throws,

    <debug> app: No copy needed.

    I dont understand why the (src_addr == dst_addr) are identical. 

    waiting for reply.

    =========================================================================

    <info> nrf_dfu_req_handler: Whole firmware image received. Postvalidating.
    <info> nrf_dfu_validation: Convert to hash to big-endian format for use in nrf_crypto
    <info> nrf_dfu_validation: Hash verification. start address: 0x1000, size: 0x6AC
    <debug> nrf_dfu_validation: Source address = 0x1000 and destination address = 0x16AC
    <debug> nrf_dfu_validation: Reading buffer at address = 0x1000 with size = 0x6AC
    <debug> nrf_dfu_qspi: nrf_qspistorage_read(addr=0x1000, src=0x200084F8, len=1708 bytes), queue usage: 1
    <warning> nrf_dfu_validation: Hash verification Passed!!!!!!
    <info> nrf_dfu_validation: Expected FW hash:
    <info> nrf_dfu_validation: 84 5F 42 4A E0 E9 54 C9|._BJ..T.
    <info> nrf_dfu_validation: 7C 95 6F CE E7 C1 D9 7B||.o....{
    <info> nrf_dfu_validation: 08 6A D9 E9 4A 44 C6 46|.j..JD.F
    <info> nrf_dfu_validation: F7 E8 9F A1 A5 BE 18 46|.......F
    <info> nrf_dfu_validation: Actual FW hash:
    <info> nrf_dfu_validation: 84 5F 42 4A E0 E9 54 C9|._BJ..T.
    <info> nrf_dfu_validation: 7C 95 6F CE E7 C1 D9 7B||.o....{
    <info> nrf_dfu_validation: 08 6A D9 E9 4A 44 C6 46|.j..JD.F
    <info> nrf_dfu_validation: F7 E8 9F A1 A5 BE 18 46|.......F
    <info> nrf_dfu_validation: Invalidating old application in bank 0.
    <debug> nrf_dfu_serial: Sending Response: [0x4, 0x1]
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 1
    <debug> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20009504, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <debug> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <debug> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20009884, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> nrf_dfu_req_handler: All flash operations have completed. DFU completed.
    <debug> app: Shutting down transports (found: 1)
    <info> app: Resetting bootloader.
    <debug> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> app: Inside main, Bootloader size = 73728
    <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.
    <debug> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> app: Enter nrf_bootloader_fw_activate
    <info> app: Valid App
    <info> app: Enter nrf_dfu_app_continue
    <debug> app: No copy needed
    <info> app: Setting app as valid
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x000FF000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 0
    <debug> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x20009504, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
    <debug> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <debug> nrf_dfu_settings: Writing settings...
    <debug> nrf_dfu_settings: Erasing old settings at: 0x000FE000
    <debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 1
    <debug> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
    <debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20009884, len=896 bytes), queue usage: 1
    <debug> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
    <info> app: Resetting bootloader.
    <debug> nrf_dfu_settings: Backing up settings page to address 0xFE000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <info> app: Inside main, Bootloader size = 73728

  • There are multiple phases in the firmware download. 

    In the first phase (after checking that the image is valid and will fit), the image is downloaded in chunks, with each chunk either stored directly at the firmware final destination (if you are single buffering or if there isn't a valid image in place already), or to the backup buffer.  The 'settings' blocks record where the incoming image is stored and also it's final destination.

    Once the image is completely downloaded and verified, the settings blocks are saved with the corresponding addresses and the next phase (where the image is copied, IF NECESSARY, from its buffer to its final destination) is begun.

    In the next phase the settings are checked and, if the final destination AND the stored address are exactly the same, the DFU code 'knows' that the image is already in it's intended location and therefore does not need to copy the image.

    In your case, since you are using the same address in QSPI memory as the final destination, hence the copy code thinks there is nothing to do. 

    The 'trick' is to have the QSPI buffer address mapped outside of the normal range of program memory so the settings blocks can distinguish between buffered image and a properly loaded image.  You can still use '1000' as a starting address in QSPI memory, but the code sets and strips off the address field used to distinguish between internal vs external memory.  In my case, I used:

    EXTERNAL_FLASH_ADDRESS=0x0A00000;

    So address 0x1000 would map to 0x0A01000 in the code.

Related