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!

