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

      

  • Hi,

    Aashyk said:
    I understand the bootloader code is different between the versions,

    It is not just the code that is different. The protocol etc. is also different. This is not generally the case between SDK versions, but the bootloader in SDK 15.3.0 is the secure bootloader, and this is a different bootloader and DFU architecture than wha tis used in the legacy bootloader. (There are similarities as the secure bootloader was based on the legacy bootloader, but that is not so relevant in this case.)

    Aashyk said:
    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)?

    This was a general point, bootloader, method to enter buttonless DFU mode, bond sharing (if you use DFU with bonding), phone side implementation - everything is different. We provide libraries for all though, so it does not mean it is a huge task. My point was just that this is a far bigger change than just the UUID numbers, so the focus must be much broader.

    Aashyk said:
    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?

    This principle remain the same. You write 1 to the buttonless characteristic (BLE_DFU_BUTTONLESS_CHAR_UUID if you use without bonds) to enter DFU mode, and that should trigger a write to GPREGRET and a reset. This is implemented by the ble_dfu service which you find under <SDK 15.3>/components/ble/ble_services/ble_dfu/.

    Aashyk said:
    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!

    The Table looks correct. Note that you do not need to think much about this as we provide libraries for it (the bootloader libraries for the bootloader, the buttonless DFU service for the application, and DFU libraries for various mobile operating systems).

  • Thanks for the reply and sorry for getting back late to this thread. From your reply, my understanding is that not only the UUID characteristic that has changed, but also the protocol and implementation for buttonless DFU has changed. I also understand that the SDK has libraries for buttonless DFU that I would be able to use out of the box.

    The problem that I'm facing is that I have implemented a custom BLE application code to handle most of the BLE services, including the legacy DFU protocol (note that I have used and still planning to use nRF SDK provided bootloader). So, it seems I would have to import the SDK to the existing application code.

    I am wondering if it would be possible to import only file dependencies relevant to buttonless DFU and if so, is there a documentation that lists those dependencies that you could point me to? 

Reply
  • Thanks for the reply and sorry for getting back late to this thread. From your reply, my understanding is that not only the UUID characteristic that has changed, but also the protocol and implementation for buttonless DFU has changed. I also understand that the SDK has libraries for buttonless DFU that I would be able to use out of the box.

    The problem that I'm facing is that I have implemented a custom BLE application code to handle most of the BLE services, including the legacy DFU protocol (note that I have used and still planning to use nRF SDK provided bootloader). So, it seems I would have to import the SDK to the existing application code.

    I am wondering if it would be possible to import only file dependencies relevant to buttonless DFU and if so, is there a documentation that lists those dependencies that you could point me to? 

Children
  • Hi,

    Ah, OK. So the question here is really just about the buttonless functionality? That is fundamentally very simple (though it can be complicated with some additional optional features). This is supported by the buttonless DFU service in the SDK, so you can base your code on that, but if you want something simple and generic you can also make something yourself. 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, for instance like this (which is adapted from the buttonless DFU service implementation in SDK 17.1.0 - components\ble\ble_services\ble_dfu\ble_dfu.c):

        err_code = sd_power_gpregret_clr(0, 0xffffffff);
        VERIFY_SUCCESS(err_code);
    
        err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
        VERIFY_SUCCESS(err_code);
    
        (void)sd_nvic_SystemReset();

    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. (The difference is if you want to use some of the additional features of the buttonless DFU service, like setting bootloader advertising name or share bonds to use encrypted link in the bootloader).

  • 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?

Related