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

OTA/DFU bootloader with increased size (BLE Secure DFU Bootloader SDK v15.3.0)

Hello,

We are using/running "BLE Secure DFU Bootloader" example from SDK v15.3.0 on our custom board (nRF52840) Softdevice v6.1.1. We added some code to the bootloader which increased its size by around 2K and now we are not able to perform DFU as the new size is greater than the existing bootloader size. Is there any way we can update the bootloader using DFU/OTA?

Also, in SDKv15.3.0 does the bootloader store the bootloader start address at MBR address space(0xFF8) and UICR register? Does updating the bootloader start address the only way to accomodate bootloader with an increased size?

Also, what is order of updating the softdevice and bootloader, which one does the MBR copy first?

Thanks.

Parents
  • Hi,

    There is no way to relocate the bootloader using SDK 15.3 (or even older SDK's on the nRF52840) via DFU. The only way to change the bootloader start address (thus making room for a larger bootloader) is by programming the new larger bootloader via SWD. With that in mind, you should also leave room for a further size increase if that may happen later.

    The reason is a consequence of your second question. SDK 15.3 only puts the bootloader start address at the end of the MBR page, and UICR is not used. It is not possible to update this without erasing the MBR page, which would brick the device.

    The order of the MBR writing the bootloader and SoftDevice should not be important (and may theoretically even change between MBR versions). The reason is that if both are updated, they need to be updated simultaneously since the new bootloader typically depends on the new SoftDevice. Therefore, MBR cannot start executing the bootloader until after both are successfully copied.

  • SDK 15.3 only puts the bootloader start address at the end of the MBR page, and UICR is not used.

    Is this still true in SDK 17.1.0? My project has a uicr_bootloader_start_address that contains the start address, and the end of my MBR is all F's. I would like to be able to increase my bootloader size via DFU.

  • No, it is not true in SDK 17.1.0. It was only used for a few releases, but caused a number of problems. In 17.1.0, the bootloader start address is written to UICR first (that is part of the bootloader hex image). When the MBR runs, it will first check the end of the MBR page, and if there is no bootloader address there it will check the UICR. If it finds it there, it will copy it to the end of the MBR page, so that it will be used in the future (so after the first boot you should see something other than FF at the end of the MBR - specifically at 0xFF8). Note that the point of this is to write protect the start address, so if the address in UICR and MBR differ, the address from the MBR is used.

    Increasing the bootloader size via DFU is not supported. First of all, the MBR is write protected by the bootloader, so the address cannot be updated (unless you first update to a temporary bootloader of the same size that does not write protect the MBR). The second problem is that writing to flash can only flip bits from 1 to 0, not the other way around. And you cannot erase the MBR page during DFU. (That in turn means that you could flip the most significant bit of the address and move the bootloader a long way down, but that would probably bee too much, and there is no way around this problem.)

Reply
  • No, it is not true in SDK 17.1.0. It was only used for a few releases, but caused a number of problems. In 17.1.0, the bootloader start address is written to UICR first (that is part of the bootloader hex image). When the MBR runs, it will first check the end of the MBR page, and if there is no bootloader address there it will check the UICR. If it finds it there, it will copy it to the end of the MBR page, so that it will be used in the future (so after the first boot you should see something other than FF at the end of the MBR - specifically at 0xFF8). Note that the point of this is to write protect the start address, so if the address in UICR and MBR differ, the address from the MBR is used.

    Increasing the bootloader size via DFU is not supported. First of all, the MBR is write protected by the bootloader, so the address cannot be updated (unless you first update to a temporary bootloader of the same size that does not write protect the MBR). The second problem is that writing to flash can only flip bits from 1 to 0, not the other way around. And you cannot erase the MBR page during DFU. (That in turn means that you could flip the most significant bit of the address and move the bootloader a long way down, but that would probably bee too much, and there is no way around this problem.)

Children
  • Hi Einar,

    Just to check if I understood correctly.

    So in order to increase BL size via DFU I should do following:

    1. In BL project comment out part which does write protection of MBR (e.g. nrf_bootloader_flash_protect(0, MBR_SIZE);)
    2. Create update package and perform DFU
    3. Change BL size (e.g. in linkerscript)
    4. In BL project add part which modify BL start address (e.g. nrf_nvmc_write_word(MBR_BOOTLOADER_ADDR, 0x000f0000);)
      1. NOTE: BL start address is changed from 0xf8000 to 0xf0000 => only one bit is changed from 1 to 0
    5. Create update package and perform DFU

    Did i miss something ?

    Thanks

  • Hi,

    This is essentially the approach, but I believe some additional steps are needed. The temporary bootloader(s) that disables write protection of the MBR also most be adjusted to copy the new larger bootloader to the new (lower) start address, and at the same time modify the MBR to use the new address. Also, the MBR will do the actual copying of the bootloader as it cannot overwrite itself while running, and that will not know about the new address at this point, so a different approach is needed.

    Therefore, I believe you will need to copy the new bootloader to the new location first, and this should be a bootloader that does not overlap with the existing bootloader. That way this can be written by the bootloader itself (a temporary one, from step 1), or a modified application or whatever is easiest to achieve. If a reset occurs at this point, things are safe, as the MBR still points to the old. Once the copy is completed, update the bootloader address in the MBR, flipping 1 bit to 0. Then after a reset, the new bootloader will run. This must still be small though, and could be the original bootloader, just built to start at a lower address. Now you can update to the new larger bootloader with normal DFU (where it is written to a temporary location and the MBR copies it in place).

    Let me reiterate that this is not officially supported and I have not tested this myself, but conceptually it should work.

Related