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

Proper way to delete bond information before DFU

Dear Nordic experts,

After experiencing a lot of random issues when retaining bond information during a DFU on some mobile devices, we've decided to choose the safest route and remove any bond information prior to performing a DFU. However, this proves to be harder than expected and I'm hoping that one of the Nordic experts here can point me in the right direction. My current process is as follows:

  • When a DFU request is received, we remove the bond by calling dm_device_delete_all()
  • After the device manager event 'context deleted' is received, we initiate the normal DFU process (bootloader_start in dfu_app_handler.c) which does the following:

...

static void bootloader_start(uint16_t conn_handle){
uint32_t err_code;
m_dfu_process_active = true;
uint16_t sys_serv_attr_len = sizeof(m_peer_data.sys_serv_attr);

err_code = sd_ble_gatts_sys_attr_get(conn_handle,
                                     m_peer_data.sys_serv_attr,
                                     &sys_serv_attr_len,
                                     BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
if (err_code != NRF_SUCCESS)
{
    // Any error at this stage means the system service attributes could not be fetched.
    // This means the service changed indication cannot be sent in DFU mode, but connection
    // is still possible to establish.
}

m_reset_prepare();

err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);
APP_ERROR_CHECK(err_code);

err_code = sd_softdevice_disable();
APP_ERROR_CHECK(err_code);

pwm_driver_deinit();

dfu_app_peer_data_set(conn_handle);

NVIC_ClearPendingIRQ(SWI2_IRQn);
interrupts_disable();

#ifdef FREERTOS
__set_CONTROL(0); // switch to MSP
#endif

bootloader_util_app_start(NRF_UICR->NRFFW[0]);
}

The problem is that in this situation, after the switch to the bootloader has been made, the bootloader doesn't want to connect with the DFU process (nrfConnect). So I am assuming that some connection context should be (re)stored after the bond has been removed. I know that the bond removal mechanism works because we use it to remove a bond on the device when the user holds a button for a while, but in that case we disconnect and power down after we receive the dm event.

What is the proper way of doing this?

Thank you in advance!

(Target: NRF52, SDK11.0, bootloader S132 dual bank)

  • Hi jj,

    It's most likely because the dfu_app_peer_data_set(conn_handle); couldn't find a central address to send to the bootloader. In the bootloader if there is no peer data is forwarded (either central address or bonding key) it will start with a new BLE address (application BLE address + 1).

    Please check dfu_transport_update_start() inside dfu_transport_ble.c

    I assume you plan to delete bond on the phone also before doing DFU update ?

    There are some option, first is to remove the code to change address in dfu_transport_update_start(). But you need to make sure bond info on the phone is also deleted.

    Another option is to modify the DFU master app to connect to the +1 address instead of the normal address. This requires modification of the DFU master app.

    A better solution is to try to retain the bond information. If you want to do that, you can tell me which issue you had. (Note that the current DFU library on Android, will try to delete bond info after it finished DFU update, you may need to modify it if you want to retain bonding).

  • Hi Hung Bui, thank you for your reply.

    The reason we decided to remove the bond info before DFU is that we've seen phone specific issues while retaining the bond, which not occured when bonding was not used. One of the issues was that with a certain phone the peripheral disconnects somewhere during the transfer (around 70%) when we use bonding while it continues flawlessly without bonding. I assume due to some connection time-out which apparently does not occur when bonding is not used. We want to be sure that the DFU process is as stable as possible and in our current experience it is most stable when we don't use bonding.

    Following your answer I am thinking of the following solution:

    • App sends DFU request
    • Peripheral receives request, store (bonded) peer address temporarily
    • Remove bond
    • During the switch to DFU, call dfu_ble_svc_peer_data_set with the previously stored address
    • Peripheral disconnects to switch to bootloader
    • Upon receiving the disconnection event in the app, remove bond on the phone
    • DFU lib tries to reconnect to peripheral in bootloader mode (which should accept the connection with the stored address)

    Would this be a suitable solution? Do you foresee any risks with this approach?

    Thanks once again!

  • Hi jj,

    yes it's fine. It's just a small inconvenient that end user have to manually remove bond on the phone.

    You can simply call dfu_ble_svc_peer_data_set() to send the address (not the bond info) to the bootloader before you delete bond on the device manager , then you switch to bootloader after you finish deleting (without calling dfu_ble_svc_peer_data_set() again).

Related