Secure buttonless DFU operation fails when DFU service is enabled after initialization

Hello,

In my application (SDK, 16.0.0, nRF 52840) I need to enable the DFU service after initialization, which I do by exposing a custom service "DFU enable". This in turn allows to read/write a uint8_t property which I check in the code, inside the DFU enable callback function (executed on BLE_GATTS_EVT_WRITE). If this uint8 is equal to a hardcoded value I execute:

ble_dfu_buttonless_init_t dfus_init = {.evt_handler = ble_dfu_buttonless_evt_handler};

......

if(app_state.enable_key==0xCA) {
nrf_gpio_pin_write(LED_2,1);
ble_dfu_buttonless_init(&dfus_init);
}

The fact that LED_2 switches on only when I write 0xCA in the custom property assures that the logic is correct and, after all, once I write 0xCA and refresh the connection the DFU icon nicely pops out on the Nordic NRFConnect app (both on my smartphone and on desktop, using a Nrf52840SDK board). However, if I select the (correctly signed) .zip and try to update the device I get the following message:

DFU failed with error: Unable to find characteristic 8EC90001F3154F609FB8838830DAEA50 for service FE59 on device DA:A9:8D:E5:90:9E.0.

I should mention that when the DFU service is started at inizialization (with exactly the same command) the service is up and running and I can complete the DFU successfully with the same zip file.

Is there smtg that I should do in addition to enabling the DFU to correctly expose the new service? From the error message It seems like the required DFU characteristics cannot be found.

Thanks!

Stefano

  • Hi Stefano,

    I do not see any explanation for this, and I was not able to reproduce it with a slightly modified buttonless example in nRF5 SDK 16.0.0 (see below). Perhaps you also do some other changes? Can you explain/show?

    diff --git a/examples/ble_peripheral/ble_app_buttonless_dfu/main.c b/examples/ble_peripheral/ble_app_buttonless_dfu/main.c
    index 978be07..ae1929f 100644
    --- a/examples/ble_peripheral/ble_app_buttonless_dfu/main.c
    +++ b/examples/ble_peripheral/ble_app_buttonless_dfu/main.c
    @@ -406,13 +406,26 @@ static void nrf_qwr_error_handler(uint32_t nrf_error)
        }*/
     
     
    +static void dfu_thing_init(void)
    +{
    +    uint32_t                  err_code;
    +    ble_dfu_buttonless_init_t dfus_init = {0};
    +
    +    dfus_init.evt_handler = ble_dfu_evt_handler;
    +
    +    err_code = ble_dfu_buttonless_init(&dfus_init);
    +    APP_ERROR_CHECK(err_code);
    +
    +
    +}
    +
    +
     /**@brief Function for initializing services that will be used by the application.
      */
     static void services_init(void)
     {
         uint32_t                  err_code;
         nrf_ble_qwr_init_t        qwr_init  = {0};
    -    ble_dfu_buttonless_init_t dfus_init = {0};
     
         // Initialize Queued Write Module.
         qwr_init.error_handler = nrf_qwr_error_handler;
    @@ -420,10 +433,7 @@ static void services_init(void)
         err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
         APP_ERROR_CHECK(err_code);
     
    -    dfus_init.evt_handler = ble_dfu_evt_handler;
     
    -    err_code = ble_dfu_buttonless_init(&dfus_init);
    -    APP_ERROR_CHECK(err_code);
     
         /* YOUR_JOB: Add code to initialize the services used by the application.
            uint32_t                           err_code;
    @@ -706,30 +716,12 @@ static void bsp_event_handler(bsp_event_t event)
     
         switch (event)
         {
    -        case BSP_EVENT_SLEEP:
    -            sleep_mode_enter();
    +        case BSP_EVENT_KEY_0:
    +            //sleep_mode_enter();
    +            NRF_LOG_INFO("Enable buttonless DFU service");
    +            dfu_thing_init();
                 break; // BSP_EVENT_SLEEP
     
    -        case BSP_EVENT_DISCONNECT:
    -            err_code = sd_ble_gap_disconnect(m_conn_handle,
    -                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    -            if (err_code != NRF_ERROR_INVALID_STATE)
    -            {
    -                APP_ERROR_CHECK(err_code);
    -            }
    -            break; // BSP_EVENT_DISCONNECT
    -
    -        case BSP_EVENT_WHITELIST_OFF:
    -            if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
    -            {
    -                err_code = ble_advertising_restart_without_whitelist(&m_advertising);
    -                if (err_code != NRF_ERROR_INVALID_STATE)
    -                {
    -                    APP_ERROR_CHECK(err_code);
    -                }
    -            }
    -            break; // BSP_EVENT_KEY_0
    -
             default:
                 break;
         }
    

  • Dear Einar,

    Thanks for your answer. In the end what worked for me was to increase the NRF_SDH_BLE_VS_UUID_COUNT parameter in the sdk_config by the number of UUIDs added (I forgot that while adding the custom service). This was somehow troubling the DFU, even though the custom characteristic I added seemd to work fine anyhow. Do you have by any chance an explanation for that?

    Thank you.

    Regards,

    Stefano 

  • Hi Stefano,

    That makes sense. You should have got an error returned when trying to add another UUID with the NRF_SDH_BLE_VS_UUID_COUNT being too low, though. So I suggest double checking that you properly check all return codes to avoid other bad surprises in the future (or risk spending longer than necessary tracking down bugs/errors in the future).

Related