Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

Implementing custom BLE transfer process in bootloader?

I'm working on a complex legacy codebase for the nRF52840, which uses nRF5 SDK 15.0.0 and the S140 SoftDevice v6.0.0. The device previously only used a custom RF protocol both in the bootloader and in the main application, but I need to add BLE support that replicates the current functionality. The biggest challenge I'm facing is that the device consists of two nRF52840 modules that undergo a handshake process in their bootloaders before each can start its main application.

I tested patching in the secure bootloader, but ran into a handful of problems. The current custom bootloader uses a watchdog timer, which was used by the previous devs as a part of the update process rather than a worst-case safety measure. It doesn't look like I would be able to replicate the functionality with the bootloader watchdog. I would also need to modify the SDK to not enter the main application after secure DFU, because this causes one module to enter its main app while the other hangs. Lastly, this method complicates the transfer of the binary for the second module.

Implementing a custom BLE service in the bootloader should be able to circumvent most of these issues, but is it possible to do this? nrf_sdh_enable_request() causes the bootloader to crash. I see in nrf_dfu_ble.c that some other functions are used to initialize the BLE stack. I can try to port the code over, but I'm not sure if it will be possible to modify it to implement NUS.

I'd greatly appreciate any feedback on how to safely implement this multiprotocol OTA DFU process, or verification that it's possible to implement regular BLE advertising and services within the bootloader.

Parents
  • Hello,

    When modifying the bootloader, it is important to note that you cannot do OTA DFU to a bootloader with a different start address. Therefore, I would recommend you assess how much free space you have to work with before spending too much effort on the implementation. It may be that it is not possible to add the BLE DFU transport without allocating more flash to the bootloader, which means you cannot update the bootloader on existing devices.

    Typical memory layout with bootlaoder: Memory layout.

    Implementing a custom BLE service in the bootloader should be able to circumvent most of these issues, but is it possible to do this?

    I don't see any problems with adding additional services, provided you have enough flash for these extra features.

    Best regards,

    Vidar

  • Thank you for your response Vidar. I managed to shoehorn a functional prototype of the custom bootloader BLE process outlined in my OP by copying the BLE library code from my main app. Among other required changes, this required me to comment out the DFU_TRANSPORT_REGISTER definition from nrf_dfu_ble.c and any references to the nRF driver watchdog from my original custom bootloader code. It looks like BLE setup in the bootloader will route to other Nordic libraries? To be clear, I don't want to use the existing Nordic infrastructure for DFU, but rather for my custom service to be the only custom service available. I would also like to keep the original code and watchdog timer usage intact. Is this still possible to accomplish?

    On the bright side, I did still get a functional and connectable bootloader build with NUS included and plenty of flash overhead remaining.

Reply
  • Thank you for your response Vidar. I managed to shoehorn a functional prototype of the custom bootloader BLE process outlined in my OP by copying the BLE library code from my main app. Among other required changes, this required me to comment out the DFU_TRANSPORT_REGISTER definition from nrf_dfu_ble.c and any references to the nRF driver watchdog from my original custom bootloader code. It looks like BLE setup in the bootloader will route to other Nordic libraries? To be clear, I don't want to use the existing Nordic infrastructure for DFU, but rather for my custom service to be the only custom service available. I would also like to keep the original code and watchdog timer usage intact. Is this still possible to accomplish?

    On the bright side, I did still get a functional and connectable bootloader build with NUS included and plenty of flash overhead remaining.

Children
  • Good to hear that you were able to make the NUS service work in the bootloader. You can probably remove the nrf_dfu.c file from your bootloader project, then declare your own nrf_dfu_init() function to initialize your custom DFU handling. nrf_dfu_init() is called from nrf_bootloader_init() when entering DFU mode. The WDT module is initialized before nrf_dfu_init().

  • Hello again Vidar. I just wanted to follow up on the code that allowed me to use custom BLE services in my bootloader. Modifying the stack initialization function to call these functions solved the problem:

    static void ble_stack_init(void) {
        uint32_t ram_start = 0;
        NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    
        nrf_dfu_mbr_init_sd();
        sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR);
        nrf_sdh_enable_request();
        nrf_sdh_ble_app_ram_start_get(&ram_start);
        nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        nrf_sdh_ble_enable(&ram_start);
    }

    One small edge case: I needed to include various nrf_bootloader*.c sources in my Makefile. Omitting them did not result in compiler or linker errors, but prevented the bootloader from being recognized. With my code changes, I am able to initialize the BLE stack, advertise, and connect without requiring a call to nrf_bootloader_init().

Related