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

BLE transport for DFU in application

Hello,

We are using nRF52840 with SDK 15.2.0, a bootloader and the SoftDevice. We communicate with another microcontroller (a STM) with I2C. The nRF52840 is the master.

Currently we are able to perform (separately) a DFU for the two microcontrollers:

  • For the nRF5284, we use the nRF Connect application on a smartphone and we launch the DFU process with a .zip file containing the new firmware. Or we can use a cellular modem then jump to the bootloader.
  • For the STM, we download the new firmware from a cellular modem to the nRF52840 Flash memory, then we send it via I2C to the STM bootloader which perform DFU.

Now, we would like to be able to perform a DFU for the STM with nRF Connect on smartphone, as we do for the nRF5284. So the idea is to create the .zip file containing the STM firmware, like we currently do with the nRF5284 firmware. Then the process for the user will be the same for the two targets: connect the nRF5284 to the smartphone, select the .zip file, launch the DFU process, and when data is stored in Flash memory we check the target (with a parameter in the .dat file):

  • If it is the nRF5284 firmware, we jump to the bootloader (like it is already done currently).
  • If it is the STM firmware, the DFU is finished on the nRF5284 side (no reset) and we send it to STM via I2C.

To do that, we need to move the BLE DFU mechanism from the bootloader to the application. I have found some information in other topics and I have searched in the source code of the bootloader and the example given here. I am not sure, but I think we need the DFU Control Point and DFU Packet Characteristics, and the BLE transport layer. We don’t need to create a custom transport, we want to do exactly like how it is done in the bootloader.

We are in SDK 15.2 and not in 15.3 so is it a problem? I have read that DFU in application was improved in 15.3.

What we have done is to add the following code from the bootloader in our application during the BLE init:

scheduler_init();

err_code = nrf_dfu_settings_init(true);
APP_ERROR_CHECK(err_code);

err_code = nrf_dfu_init(m_user_observer);
APP_ERROR_CHECK(err_code);

The BLE transport layer is not modified, in the file nrf_dfu_ble.c:

DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const ble_dfu_transport) =
{
    .init_func  = ble_dfu_transport_init,
    .close_func = ble_dfu_transport_close,
};

Now we can see in nRF Connect the same BLE characteristics with the bootloader and with the application. But if we launch the DFU from the smartphone, the process is blocked during the first data write, without answer from the application.

The problem occurs in the ble_evt_handler in the file nrf_dfu_ble.c for the case BLE_GATTS_EVT_WRITE in the function on_write(&m_dfu, p_ble_evt);

The function begins with the code

ble_gatts_evt_write_t const * const p_write_evt = &p_ble_evt->evt.gatts_evt.params.write;

if (p_write_evt->handle != p_dfu->dfu_pkt_handles.value_handle)
{
    return;
}

And the if condition is false so the data is not stored.

I don't know if this is the main problem or only the result of another problem. Is it the good way to move the DFU process in the application? Or perhaps you have a good example for us? We try to do the less modifications as possible in the code because we only want to reproduce what the bootloader do.

Thanks for your help!

  • Hi,

    Now we are on SDK 15.3 with SoftDevice 6.1.1 and the secure bootloader from the example in SDK. We have set the flags NRF_BL_DFU_ALLOW_UPDATE_FROM_APP and NRF_DFU_SUPPORTS_EXTERNAL_APP in sdk_config.h for the bootloader.

    We are able to do exactly what we want, the external firmware is written in Flash and when the application is restarted we perform the DFU of the other microcontroller and we invalidate the bank 1 in memory. So thank you for your help for this part.

    But now we have another problem with the bootloader: thanks to this previous thread, we were able to do a DFU after using our own firmware download process in Flash and modifying the bootloader settings. With this new bootloader, the application data swap in memory is correctly done but after that, the app is not started and the bootloader seems to be stuck in a faulty state because we can not detect it in BLE. So we have no way to retreive the app without reprogramming the nRF52840.

    If something is wrong with our data or the bootloader settings, the bootloader must abort the DFU and keep the current application in bank 0. But we can see the swap of bank 1 in bank 0 in memory so it is strange to not start correctly the new application after that.

    We can see the settings management is not exactly the same with SDK 15.3, have you any idea to solve our problem? Thanks for your help.

  • Hi,

    Is it possible to use RTT logging to see what happens in the bootloader? Without knowing more I suspect that you may be getting problems with the bootloader settings backup. Perhaps you could add all fields to settings_forbidden_parts_copy_from_backup() and see if that does anything (effectively omitting the setting backup feature)?

  • With the help of this thread we have found our problem. You are right, it was the settings backup. We have bypassed it in the bootloader and we have updated the settings in version 2 in the application.

    Now it works as expected, we can perform a DFU with BLE or modem, and for the two microcontrollers.

    Thank you, the problem is solved!

Related