Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

DFU SVCI initialisation crash when adding DFU buttonless service after disabling and re-enabling softdevice

Hi Nordic team,

Due to critical real time constraints, I have to temporarily disable the softdevice, perform data acquisition from sensors, then enable it again.
I'm using softdevice s130 v5.0.0 on nRF52832 and SDK 14.2.0 for both application and bootloader
Currently I'm doing the following:

// In main.c

int main(void) 
{
// Some hardware initialization...

nrf_drv_clock_init();
nrf_drv_clock_hfclk_request(NULL);

sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
sd_power_mode_set(NRF_POWER_MODE_LOWPWR);

ble_stack_init();
gap_params_init();
gatt_init();
services_init();
advertising_init();
conn_params_init();
advertising_start();

//....

}

In services_init function, I added Device Information service, Battery service, one custom service and the buttonless DFU service:

void services_init(void)
{
    // Add DIS
    // Add BAS
    // Add custom  service
    
    memset(&dfus_init, 0, sizeof(dfus_init));
    dfus_init.evt_handler = ble_dfu_evt_handler;

    // Initialize the async SVCI interface to bootloader.
    err_code = ble_dfu_buttonless_async_svci_init();
    APP_ERROR_CHECK(err_code);

    err_code = ble_dfu_buttonless_init(&dfus_init);
    APP_ERROR_CHECK(err_code);
}

I have added softdevice state observer using NRF_SDH_STATE_OBSERVER macro to track softdevice state when disabling/enabling it:

NRF_SDH_STATE_OBSERVER(m_sd_state_observer, 0) = {
    .handler = sd_state_evt_handler,
    .p_context = NULL,
};

static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void *p_context)
{
    switch (state)
    {
    case NRF_SDH_EVT_STATE_ENABLE_PREPARE:
        break;

    case NRF_SDH_EVT_STATE_ENABLED:
        sd_enabled = true;            
        break;

    case NRF_SDH_EVT_STATE_DISABLED:
        sd_disabled = true;         
        break;

    default:
        break;
    }
}

In my application code, I disable the softdevice by calling nrf_sdh_disable_request:

sd_ble_gap_adv_stop();
sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
err_code = nrf_sdh_disable_request();
APP_ERROR_CHECK(err_code);
while(!sd_disabled){}
// Perform critical timing work...

And then I re-enable the softdevice by calling nrf_sdh_enable_request:

err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);

// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);

// Overwrite some of the default configurations for the BLE stack.
ble_cfg_t ble_cfg;
memset(&ble_cfg, 0, sizeof(ble_cfg));

// Three vendor-specific UUIDs: our own, Nordic's DFU service and Nordic's
// UART service.
ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 2;
err_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, ram_start);
APP_ERROR_CHECK(err_code);

// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);

And when I receive softdevice enabled notification (NRF_SDH_EVT_STATE_ENABLED) I reconfigure gap, gatt, adv, conn, and all services and restart advertisement:

gap_params_init();
gatt_init();
services_init();
advertising_init();
conn_params_init();
advertising_start();

Every thing is working as expected, except adding the DFU buttonless service after disabling the softdevice and enabling it again, the application crashes when calling nrf_dfu_set_adv_name_init function (ble_dfu_unbonbed.c) which is called inside ble_dfu_buttonless_async_svci_init function!

uint32_t ble_dfu_buttonless_async_svci_init(void)
{
    uint32_t ret_val;

    ret_val = nrf_dfu_svci_vector_table_set();
    VERIFY_SUCCESS(ret_val);

    ret_val = nrf_dfu_set_adv_name_init();
    VERIFY_SUCCESS(ret_val);

    ret_val = nrf_dfu_svci_vector_table_unset();

    return ret_val;
}


The only workaround that I did for the moment is to call ble_dfu_buttonless_async_svci_init only once during the first call to services_init at device power-up, and do not call it (ble_dfu_buttonless_async_svci_init) when adding services after disabling and re-enabling softdevice, After doing this the DFU is still working without problem.

So I would like to know if this workaround is safe?

And I would be grateful if someone could check why nrf_dfu_set_adv_name_init function crashes when it is called after disabling then enabling the softdevice.

thank you in advance,

Best Regards.

  • Hello,

    What does nrf_dfu_set_adv_name_init() return when the application crashes?

    And what sort of bootloader did you flash? Was it the BLE bootloader?

    Best regards,

    Edvin

  • Hi,

    Thank you for your quick reply, I'm using bootloader_secure_ble example in SDK 14.2.0

    Now, I was trying to reproduce the same behavior that I mentioned in my question, but what I get is a weird behavior:

    The nrf_dfu_set_adv_name_init sometimes returns NRF_SUCCESS:

    and then application is hanging at the first instruction in the nrf_dfu_svci_vector_table_unset at NRF_LOG_INFO and does not return! and still blocked at __sd_nvic_irq_enable():

    And sometime is still blocked at a different instruction! and sometime is works fine!

    I tried to comment out the call the NRF_LOG_INFO in the nrf_dfu_svci_vector_table_unset function (as it is 90% failing at this level), the application still hanging at nrf_dfu_set_adv_name_init and don't return, it still blocked:

    So as you can see once the nrf_dfu_set_adv_name_init is getting executed (after disabling and enabling again the softdevice) I start having a weird behavior!

    I'm start wondering if it is not an issue related to interrupts enable/disable between the applicaton, bootloader

     and softdevice?

  • Hi

    Good news, I think that I have found the root cause of this weird behavior!

    Actually, I have found a DFU SVCI initialization issue that was raised and reported it the DFU SVCI initialisation, missing critical section discussion in the devzone and I have applied the provided patch, which adds a critical section while temporarily redirecting interrupts to bootloader and the problem was solved Relaxed

Related