Using BLE OTA DFU to update the Bootloader itself

Hi,

We develop in an OpenSuse VM so that we all have the benefit of only having to setup the tools once.  Segger Embedded Studio was building our variant of the DFU Bootloader example.  We use the debug version of the project since we have security key checking turned off for the time being.  When we use a Jlink and SES to program one of our target boards containing the nrf52833 the target programs correctly and we get an MBR, SoftDevice S113, a bootloader, and and MBR parameters page and Bootloader Settings page that all seem to work together.  However, when we try to package up the bootloader app and generated bootloader settings page, with a small update, just the advertising name to show that the update worked, the OTA DFU (using nrf connect on an android phone to send the .zip file) the update appears to work, but the new advertising name does not show up, until I erase the chip and use SES to update the target hardware. 

I have attached a link to our zipped repo of the modified DFU example.
The modified DFU example code is here:  https://drive.google.com/file/d/1AynGuAxH_khmbu_RpCUoxpiVGjGaK0PB/view?usp=sharing  

We had to change the BOOTLOADER_START_ADDR to be 0x71000 instead of the 0x78000 used in the original SDK example because we compiled in uECC for the security library.  I changed this in the project options section placement macros in SES to FLASH_START=0x71000.  Do I need to change that somewhere else as well?  The reason I ask is that location 0x0FF8 and NRF_UICR->NRFFW[0] the shows different addresses when I look at the flash I read out with the Jlink after programming through SES and the generated hex file in the output/exe folder.

In our repo we have a script IsaacPackageDfuForDFU to package the bootloader hex and settings hex into a .zip file for OTA DFU using an android phone.  The relevant lines are:
nrfutil settings generate --family NRF52 --application $DFU_DBG_EXE --application-version 0 --bootloader-version 2 --bl-settings-version 2 $DFU_DBG_SETTINGS_FILE

In_The_Field Production_Unit_Readback.hexActall_HDT_NG_Bootloader_S113_Debug.hexmergehex -m $DFU_DBG_SETTINGS_FILE $DFU_DBG_EXE -o merged.hex
nrfutil pkg generate --debug-mode --hw-version 52 --application-version 0 --application merged.hex $DFU_DBG_APP_FILE

After I package the bootloader and attempt to update it OTA, it seems like the DFU update took, but rebooting the hardware does not cause advertising, not with the advertising name NRF_DFU_BLE_ADV_NAME "DfuTarg" of the original image that was in the hardware or with the updated NRF_DFU_BLE_ADV_NAME of "Actall_Temporary".

Do I need to be packaging up a MBR settings page as well?  If I did that would it even help since the bootloader start address has been modified and there is a hard coded address inside the MBR code that is packaged with the softdevice?

Our issue is that we have a thousand units in the field with just the bootloader and no app in them.  We can add the app once, but then we can never update it again because the DFU will always jump to the app after that.  So we want to update the custom bootloader we put in there to our new custom bootloader that will jump to DFU if a button is held down at boot.  We can make this work when programmed with a J-link, but we can't do it over the air which means we would need to open the cases of the 1000 units in the field that contain just the bootloader and use a Jlink and a cable to update the bootloader.

I have attached a hex file of the image we have in units in the field which only allow us to update the application once as well as the hex being generated by SES for the improved hold-the-button-on-boot-to-DFU version of the bootloader Actall_HDT_NG_Bootloader_S113_Debug.hex.  

If it helps, I can give you access to the whole linux dev environment virtual machine, although it is 14 GB to download.

Any hints as to what I may be doing wrong?


Parents
  • We actually have the larger bootloader expanded and using uECC in the units in the field.  That bootloader works.  Well it will work once and then forever jump to the installed app.  So we are not trying to change the size of the bootloader from what is already in the target hardware.  I would assume we could leave the MBR and Softdevice in there, and just update the bootloader itself.  Is that not possible?

Reply
  • We actually have the larger bootloader expanded and using uECC in the units in the field.  That bootloader works.  Well it will work once and then forever jump to the installed app.  So we are not trying to change the size of the bootloader from what is already in the target hardware.  I would assume we could leave the MBR and Softdevice in there, and just update the bootloader itself.  Is that not possible?

Children
  • Hi,

    1) What values do you read from 0x0FF8 and NRF_UICR->NRFFW[0] (0x10001014). These should hold the start address of the bootloader and never change.

    2) Since you are using the debug version of the bootloader, which has RTT logging enabled by default. Could you get the RTT log and upload it here?

    3) Which SDK version are you using?

    I would assume we could leave the MBR and Softdevice in there, and just update the bootloader itself.  Is that not possible?

    That is possible.

  • From the attached hex file In_The_Field-Production_Unit_Readback.hex.  I assume that the bytes for a 32 bit absolute address are in reverse order and that the address at 0X0FF8 in hex below is our intended address of 0x00071000. 

    :200FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0010070000E007000B

    Looking at NRF_UICR->NRFFW[0] (0x10001014) from the same in the field readback of hex file the address appears to be unwritten and all 0xFFs.  I assume this doesn't matter as I saw in the documentation that the MBR jumps first to the address specified at 0x0FF8 and ignores the address in the NRFFW[0] slot if an address is held in the MBR at 0x0FF8.

    :020000041000EA
    :20100000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0


    We lowered the bootloader start address from 0x78000 to 0x71000 to make room for uECC.

    When I try to update the bootloader only, packaging using nrfutil with the following syntax

    nrfutil pkg generate --debug-mode --hw-version 52 --application-version 1 --application $DFU_DBG_EXE $DFU_DBG_APP_FILE

    The hex that I read out from the device, which no longer will advertise, has what I believe to be the original bootloader in its original location of 0x71000 and the new bootloader written at 0x1C000 instead of at 0x71000 as is specified in the hex file that nrfutil zipped up.  The unit no longer advertises as it would if I had written the new bootloader with SES instead of doing an OTA update.  The NRF_UICR->NRFFW[0] (0x10001014) location is still all 0xFFs.

    When I take a unit that has the old production bootloader in it at 0x71000 and try to do an OTA DFU with the nrfutil syntax changed to use --bootloader $DFU_DBG_EXE instead of  --application $DFU_DBG_EXE, the failure mode is different.  The unit still advertises the BLE advertising name of the old bootloader (DfuTarg) and the hex that I read out is unchanged.  I also see no progress bar in nrf connect for android so I assume some kind of validation on upload of the new bootloader failed.

    I have not brought back the old commit for the Bootloader that is in the field, so I can debug into it to get an RTT log.

    We are using SDK version 17.0.2.





  • When I use SES to flash the new bootloader 0.0.01, and then try to load the bootloader package I built with the --bootloader nrfutil flag instead of the --application flag, the debug output shows:

    <info> nrf_dfu_validation: Signature required. Checking signature.
    <warning> nrf_dfu_validation: No signature found.
    <warning> nrf_dfu_validation: Prevalidation failed.


    When I use SES to flash the new bootloader 0.0.01, and then try to load the bootloader package I built with the --application flag, the debug output shows this loop:


    <info> app: main(): BLE DFU Version 0.0.01
    <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.
    <info> app: main(): BLE DFU Version 0.0.01
    <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.
    <info> nrf_dfu_settings: Bac
    <info> app: main(): BLE DFU Version 0.0.01

  • Hi,

    idavenport said:
    When I use SES to flash the new bootloader 0.0.01, and then try to load the bootloader package I built with the --application flag, the debug output shows this loop:

    I'm not sure if this makes sense. Are you trying to update the bootloader like it was an app?

    idavenport said:

    When I use SES to flash the new bootloader 0.0.01, and then try to load the bootloader package I built with the --bootloader nrfutil flag instead of the --application flag, the debug output shows:

    <info> nrf_dfu_validation: Signature required. Checking signature.
    <warning> nrf_dfu_validation: No signature found.
    <warning> nrf_dfu_validation: Prevalidation failed.

    Seems like you are missing the private (signing) key when generating the DFU package. Try adding this to your "nrfutil pkg generate" command:

    --key-file key.pem

  • We were able to update/upload our main application without having to use a key file.  Is there a separate setting for removing the encryption requirement from --application updates vs. --bootloader updates?

Related