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

OTA DFU Bootloader SDK6.1

We've got devices that are out in the field which were built on SDK6.1 w/ 110 SoftDevice 7.1.0 on an nRF51822.

Went with the dual-banked solution as that was what was available at the time of development, but we've run up against the allowed codespace w/ the dual-banked solution. I've been able to get the Single Bank solution working, and am able to use it w/ nRF Toolbox to load our Application image, but have not been able to successfully use nRF Toolbox to update our existing dual-bank bootloader.

I've been referencing the Master Control Panel Init Packet Handling -- and used the nrfutil.exe in the latest Master Control Panel (3.10..) to generate a package (ZIP) -- but when I attempt to DFU, I get the following error: "Init packet with 2-byte CRC supported. Extended init packet found."

My understanding is that the 2-byte CRC is what was supported in the early SDK6.1 that we used. I'm (ideally) wanting to use the nrfutil.exe application to generate the appropriate package that is compatible with the dual-bank bootloader that exists on our devices in the field.

Any pointers would be greatly appreciated.

Thanks! -Tim

  • On further testing -- it seems like the bootloader.hex file can indeed be loaded with nRF Toolbox -- however, the fact that the Single Bank Bootloader wants to start at 0x3A000 instead of 0x3C000 seems to be causing issues. I'm able to update the bootloader to the existing Dual Bank bootloader, and it works fine, but not when I load the Single Bank hex file.

    Is there something I'm missing?

  • Hi,

    Unfortunately, the example bootloader is not able to change its start address. So the start address in new and old bootloader should be the same. The reason we don not support is that it would be harder if possible to make it as fail-safe as it is with the current implementation.

    Would it be possible to reduce the size of your single bank bootloader so it can start at 0x3C000 in your case? That would be the preferred option. Otherwise it may be possible to work around it by using the SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET to change the interrupt forwarding address so the MBR does not forward program execution to the old address in UICR.BOOTLOADERADDR. Note that UICR registers cannot be updated at runtime since a full chip erase is required to erase them (NVMC.ERASEALL).

    Also note that the new bootloader does not foresee the change in the bootloader memory map when going from dual bank to single bank, which causes the the "bootloader update complete" verification to fail.

    Normal program flow when doing bootloader update:

    • When doing DFU of new bootloader the old bootloader loads the new image to swap and sets
      p_bootloader_settings->bank_1 ==
      BANK_VALID_BOOT followed by a system reset
    • Bootloader starts and
      bootloader_dfu_sd_in_progress()
      returns 'true' since BANK_VALID_BOOT is set in bootloader settings.
    • in bootloader_dfu_sd_update_continue() the bootloader compares its own image with the one in swap. If they are different the old bootloader will assume that the one in swap is a new one. In this case it will be different
    • The comparison will return false so the bootlaoder runs the dfu_bl_image_swap() call to replace itself with the new one (swap is handled in the MBR).
    • The MBR will start the new bootlaoder once the copying is complete.
    • BANK_VALID_BOOT will still be set when the new bootloader starts, but this time the comparison in bootloader_dfu_sd_update_continue() will return success so the bootlaoder will proceed to bootloader_dfu_sd_update_finalize() call and clear the BANK_VALID_BOOT flag.

    However, in your case you will likely see that the bootloader runs the verification starting from BANK_0 instead of the old BANK_1 address, hence causing the bootlaoder to replace itself with an empty image from BANK_0. The workaround is to perform comparison on both new and old address in the new bootloader and check if either returns true. If one of them is true it means that the bootloader should proceed to bootloader_dfu_sd_update_finalize(). Answered a similar case here.

    The init packet requirement was added in SDK 7.0.0, and this is the format that nrfutil follows.

  • Other than the Single Bank Bootloader on GitHub (github.com/.../nrf51-dfu-single-bank-ble) -- are there any other examples that I could use as a starting point?

    It also seems the latest update to the iOS nRF ToolBox has rendered that Single Bank bootloader on GitHub non-operational -- at least for me. It now returns an error code after it gets past 65760 bytes and says that only 224 bytes were received (seems oddly close to >65535?).

  • I think the github example is a good starting point if you are using SDK 6.x.x. The other alternative is to use one of the bootloader examples from SDK 7.x.x or later.

    Packet receipt notification reports the number of received packet to the DFU controller. Problem is that the old bootloader example only had an uin16_t variable to hold the number of bytes, hence overflowing after >65535 received bytes. Fix is to declare the "m_num_of_firmware_bytes_rcvd" variable in dfu_transport_ble.c as a uin32_t.

Related