Characteristic UUID for buttonless bootloader changes between nrf SDK v.11.0.0 and SDK v15.3.0

Hello, 

I have been working with a BLE custom board project for a few months and the product requires buttonless DFU feature. The bootloader that I initially used was derived from SDK v.11.0.0 but I realized it didn't have all the features required for secure bootloading though buttonless DFU. Currently, I have successfully updated the bootloader to v.15.3.0 but the realized the buttonless DFU feature no longer works. Reading the documentation for both versions, I couldn't find the UUIDs for control point to which the designated value is written to initiate the DFU process. Has the value of NORDIC_VENDOR_BASE_UUID from v.15.3.0 example change from the base UUID represented in v.11.0.0? 

Parents
  • Hi,

    The UUIDs are different, yes. The UUID for the Secure bootloader service is 0xFE59 (see also documentation for the buttonless secure DFU service that is used to trigger DFU mode). Note that it it is not only the UUID that is different between the SDK 11 legacy bootloader and the SDK 15.3 secure bootloader - they are in fact completely different. So you cannot re-use any DFU related code going from the legacy DFU bootloader to the secure DFU bootloader.

  • Thanks for the response! I understand the bootloader code is different between the versions, but I would like to know what does it mean for the DFU function on the application code? When you mention that we can't reuse any DFU related code, do you mean the functions provided in the SDK, or examples or both (on application that is)? In my application code, I only check for the control point characteristic to see if it received the value 0x0001 and set the GPREGRET TO 0XB1 and reset start the device to enter the bootloader code. Has that changed in the new version? Also, I want to make sure if I have understood the updated UUIDs right, so I have attached a table here; If you can verify and confirm, that would be greatly appreciated!

    UUID list UUID number for version 11.0.0 UUID number for version 15.3.0
    DFU OTA primary service 00001530-1212-EFDE-1523-785FEABCD123 FE59
    Control point UUID 00001531-1212-EFDE-1523-785FEABCD123 8EC90001-F315-4F60-9FB8-838830DAEA50
    Packet UUID 00001532-1212-EFDE-1523-785FEABCD123 8EC90002-F315-4F60-9FB8-838830DAEA50
    DFU with bonds n/a 8EC90003-F315-4F60-9FB8-838830DAEA50
    DFU without bonds n/a 8EC90004-F315-4F60-9FB8-838830DAEA51

      

  • Thanks for the response! Sorry I couldn't keep up with this thread as soon as possible.

    There is no obligation for you to use the same mechanism for the buttonless feature as we do in our libraries (including same UUIDs) - you can do whatever you like. When the bootloader enters DFU mode, DFU operation will commence the same regardless.

    I think I should establish what the bigger goal of my project is before continuing with the technical questions. I have implemented the application code for my project using custom build environment and have implemented the custom BLE protocol to simulate UART over BLE and send & receive commands from and to a central device (Android and iPhone) using the s132 6.1.1. After implementing mentioned features, we decided to include the DFU OTA feature into the product, so we ended up using the custom bootloader based on SDK v11.0.0 (not sure if they were compatible with s132 6.1.1., but they worked without issues) and also used the Nordic Toolbox app on the mobile side to perform the OTA Device firmware updates.

    Later in the project, I have realized that the project requirements had been updated to have cybersecurity features, which would include device bonding, secure bootloader (cryptographic signature & application version checking), which were not available in the SDK v.11.0.0. which is okay since the bootloader based on SDK 15.3.0 had those features out of the box and is meant to work with s132 6.1.1, and hence the decision to upgrade to the bootloader from SDK v15.3.0

    Broader Goals for the project:

    1. Application: Implement buttonless DFU which supports bonding, (compatible with existing custom application code)
    2. Bootloader: Implement secure bootloader with cryptographic signature and version checking (Use Nordic semiconductor's secure bootloader, assuming it's efficient to modify application code that's compatible than writing a bootloader code from scratch)
    3. Mobile app: Implement the DFU OTA code that is compatible with device code, which would be both custom application code and the bootloader (Use Nordic semiconductor's Android and iOS library, assuming it's efficient to modify application code that's compatible than writing a mobile app code from scratch)  

    The real issue is that I hadn't used the SDK v15.3.0 to develop my application code and the development has progressed to the point where it's no longer feasible to introduce the SDK libraries into the application code.

    Current goal for this project is making number 1. the custom application code that is compatible with Number 2. and 3. the bootloader and mobile app, hopefully without having to import all of the SDK functionalities. That's the reason why I would like to know how the bootloader works (and the mobile app as well in future) to make the application code compatible with them, as the result spawning this thread

    So, back to the matter at hand...

    In a nutshell you only need a characteristic you write something to, to indicate that the nRF should enter DFU mode. Then the nRF just need to write a magic word to GPREGRET and reset

    So, I implemented the code as you had suggested, and I was able to get the device to reset and get into the bootloader mode. but it seems that the bootloader recognizes the GPREGRET magic number but doesn't recognize the firmware update. I was able to perform the OTA DFU with the same bootloader when there is no application code on the device though. From the debug terminal, on line 12 we can see the GPREGRET initiated the DFU mode but doesn't seem to perform the actual update. (and code jumps to the application code right after) 

    <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: Backing up settings page to address 0x7E000.
    <debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
    <debug> app: Enter nrf_bootloader_fw_activate
    <info> app: No firmware to activate.
    <debug> app: App is valid
    <debug> app: DFU mode requested via GPREGRET.
    <info> nrf_bootloader_wdt: WDT enabled CRV:327680 ticks
    <info> nrf_bootloader_wdt: Starting a timer (324480 ticks) for feeding watchdog.
    <debug> app: timer_activate (0x20005994)
    <debug> app: in weak nrf_dfu_init_user
    <debug> app: timer_stop (0x20005984)
    <debug> app: timer_activate (0x20005984)
    <info> app: Entering DFU mode.
    <debug> app: Initializing transports (found: 1)
    <debug> nrf_dfu_ble: Initializing BLE DFU transport
    <debug> nrf_dfu_ble: Setting up vector table: 0x00071000
    <debug> nrf_dfu_ble: Enabling SoftDevice.
    <debug> nrf_dfu_ble: Configuring BLE stack.
    <debug> nrf_dfu_ble: Enabling the BLE stack.
    <debug> nrf_dfu_ble: No advertising name found
    <debug> nrf_dfu_ble: Using default advertising name
    <debug> nrf_dfu_ble: Advertising...
    <debug> nrf_dfu_ble: BLE DFU transport initialized.
    <debug> nrf_dfu_flash: Initializing nrf_fstorage_sd backend.
    <debug> app: Enter main loop
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed

    Here's a screenshot from the Android DFU app (recently split from the Toolbox app),

    The OTA DFU does work when there is only bootloader on the device. It's only when the buttonless DFU is initialed, the functionality doesn't work

    Also, I think the topic question has been answered, so let me know if I need to create a new topic to continue conversation on the buttonless DFU feature

  • Hi,

    Thanks for providing the background for the questions - that is always useful to know.

    Aashyk said:
    From the debug terminal, on line 12 we can see the GPREGRET initiated the DFU mode but doesn't seem to perform the actual update. (and code jumps to the application code right after) 

    Yes, Based on your bootloader log I see that DFU mode is entered based on GPREGRET and the BLE transport is initialized, so it should start to advertise, and the phone (DFU master) should be able to connect and perform DFU at this point but that does not seem to happen.

    Do you get any more logs before the application starts or is this it? Also, how long does it take before the application is started? Can you check the RESETREAS register after starting the app again to see if the reset was caused by a WDT reset (even though it should have been fed)? Or for instance check if this happens if you test without enabling the WDT (just to rule it out)? It would also be interesting if you could check if you see the bootloader advertising when it should be in DFU mode (before something happens and the app is started)?

    Aashyk said:
    Also, I think the topic question has been answered, so let me know if I need to create a new topic to continue conversation on the buttonless DFU feature

    Generally opening new cases for new (not directly related) questions is a good idea. As we are already starting with this it is OK to continue here, but if you make new cases for new questions in the future that would be much appreciated Slight smile

  • Do you get any more logs before the application starts or is this it? Also, how long does it take before the application is started?

    Yeah, there are logs on the WDT timer feed and the application starts right after the end of the log. The device gets out of the bootloader two minutes after entering the bootloader. Here is the rest of log:

    <debug> app: Enter main loop
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005994)
    <debug> app: timer_fire (0x20005994)
    <debug> app: timer_activate (0x20005994)
    <info> nrf_bootloader_wdt: Internal feed
    <debug> app: timer_stop (0x20005984)
    <debug> app: timer_fire (0x20005984)
    <info> app: Inactivity timeout.
    <debug> app: Resetting bootloader.
    <info> nrf_dfu_settings: Backin<info> app: Inside main
    <debug> app: In nrf_bootloader_init
    <info> app: MAIN: last_reboot_reason = 0
    <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

    The RESETREAS seems to be zero as well.

    for instance check if this happens if you test without enabling the WDT (just to rule it out)?

    So, I tried disabling the WDT on the application and now the device stays in bootloader but the firmware still doesn't update. But I can update the firmware through OTA once the device is stuck in the bootloader and before the bootloader timeout reset takes place.

    It doesn't seem the WDT being the issue since the bootloader feeds the watchdog properly, and the issue persists even with the WDT turned off.

  • Hi,

    Aashyk said:
    But I can update the firmware through OTA once the device is stuck in the bootloader and before the bootloader timeout reset takes place.

    I see - what exactly is the issue then? Is it that the phone app does not automatically connect to the device after it entered DFU mode and you need to scan for devices and connect to it again, and then do the DFU? Or something else?

  • Is it that the phone app does not automatically connect to the device after it entered DFU mode and you need to scan for devices and connect to it again, and then do the DFU? Or something else?

    Yes, the phone app fails to recognize that the device is in the bootloader and therefore the device times out of bootloader and enters the application code after a while. If I abort and restart the DFU process before the device jumps to the application code, OTA DFU works.

    I am wondering if I have missed some key information with implementing the buttonless feature on the application code so that it is compatible with the Nordic DFU app

Reply
  • Is it that the phone app does not automatically connect to the device after it entered DFU mode and you need to scan for devices and connect to it again, and then do the DFU? Or something else?

    Yes, the phone app fails to recognize that the device is in the bootloader and therefore the device times out of bootloader and enters the application code after a while. If I abort and restart the DFU process before the device jumps to the application code, OTA DFU works.

    I am wondering if I have missed some key information with implementing the buttonless feature on the application code so that it is compatible with the Nordic DFU app

Children
  • Hi,

    I can think of a few reasons that is worth checking out.

    First of all, are you using the buttonless DFU service from later SDKs now, or are you using the old (legacy) buttonless DFU service? If there is a mismatch between the buttonless DFU service (secure or legacy) and the DFU service in the bootloader, the app may filter on wrong parameters when scanning for the device again after it has reset into DFU mode.

    Secondly, is the BLE address incremented by 1 while in bootloader mode? That should always be done when using DFU without bonding in the bootloader, also in the legacy bootloader, but it is worth double-checking.

  • First of all, are you using the buttonless DFU service from later SDKs now, or are you using the old (legacy) buttonless DFU service? If there is a mismatch between the buttonless DFU service (secure or legacy) and the DFU service in the bootloader, the app may filter on wrong parameters when scanning for the device again after it has reset into DFU mode.

    By buttonless DFU service, do you mean the BLE service set with the UUID 0xFE59. If so yes, and the corresponding characteristics (control, packet and without bonding) from the table above.

    Secondly, is the BLE address incremented by 1 while in bootloader mode? That should always be done when using DFU without bonding in the bootloader, also in the legacy bootloader, but it is worth double-checking.

    Yeah, it is present in the bootloader under the function gap_address_change() which is called by gap_params_init(), which in turn is called by the function, ble_dfu_transport_init()

  • So you are using the buttonless service (with the correct "new" UUIDs from SDK 15.3 (or other "new" SDK with the secure bootloader? And you are using the secure bootloader. If so, then that should be good. Then I do not immediately have any other ideas.

    Perhaps to get more info you could test with nRF Connect for Android instead - does it fail to connect after entering DFU mode as well? If so, can you upload the full debug log from the app here? You could also make a sniffer trace of the communication both when entering DFU mode and of the nRF advertising afterwards. That way we would know both what happens on air, what the nRF is advertising after entering DFU mode and what the Android log says. Looking at that together could hopefully give some pointers.

Related