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

Proper Way to Temporarily Disable Softdevice

What is the proper way to temporarily disable the softdevice? Currently I have the following

  sd_ble_gap_adv_stop();

  bool disabled_softdevice = false;
  if (nrf_sdh_is_enabled())
  {
    nrf_sdh_disable_request();
    while (nrf_sdh_is_enabled()) {}
    disabled_softdevice = true;
  }

  nrf_nvmc_write_bytes((uint32_t)&NRF_UICR->CUSTOMER[0], ...);
  ...

  if (disabled_softdevice)
  {
    nrf_sdh_enable_request();
    while (!nrf_sdh_is_enabled()) {}
    disabled_softdevice = false;
  }

But soon after reenabling the softdevice asserts with the following callstack

SWI2_EGU2_IRQHandler
nrf_sdh_evts_poll
nrf_sdh_ble_evts_poll

where sd_ble_evt_get returns error code 0x4001.

  • HI Andreas, 

    which SDK and SoftDevice versions are you using?

    According to the S132 API doc sd_ble_evt_get should not return 0x4001. In fact 0x4001 is NRF_FAULT_ID_SDK_ERROR , i.e. an error stemming from a call to APP_ERROR_CHECK or APP_ERROR_CHECK_BOOL.

    Could you debug the project and set a breakpoint in app_error_handler and app_error_handler_bare and see if you end up there? If so post the call stack and the debug log output here.

    Best regards

    Bjørn

  • Ah the error code is 0x3001 (seems like a weird behavior in the Ozone debugger that it displays 0x4001 in some situations).

    The SDK version is 14.0.0 and the Softdevice is S132 v5.0

    And yes, the breakpoint reveals the callstack

    SWI2_EGU2_IRQHandler
    nrf_sdh_evts_poll
    nrf_sdh_ble_evts_poll Line 291
    app_error_handler
    app_error_fault_handler

    Seems weird that error code 0x3001 would be raised despite this loop

    while (!nrf_sdh_is_enabled()) {}

    Also, the error happens after this code is executed since setting a breakpoint at

    disabled_softdevice = false;

    delays the crash until execution after stopping at the breakpoint is resumed.

  • Looking up 0x3001 I see that  BLE_ERROR_NOT_ENABLED is defined as (NRF_ERROR_STK_BASE_NUM(0x3000)+0x001). So it would seem that you're calling sd_ble_evt_get() without having enabled the SoftDevice first. 

    Otherwise, the APP_ERROR_HANDLER(ret_code) at line 291 in nrf_sdh_ble_evts_poll() should only be called if  be called if sd_ble_evt_get returns NRF_ERROR_INVALID_ADDR (0x10) or NRF_ERROR_DATA_SIZE(0x0C). 

  • Just tried a minimal example to reproduce the behavior.

    I used the example project ble_peripheral/ble_app/bms with the following git patch

    diff --git a/examples/ble_peripheral/ble_app_bms/main.c b/examples/ble_peripheral/ble_app_bms/main.c
    index bf00c8ca..9c87c961 100755
    --- a/examples/ble_peripheral/ble_app_bms/main.c
    +++ b/examples/ble_peripheral/ble_app_bms/main.c
    @@ -939,6 +939,21 @@ int main(void)
         // Start execution.
         NRF_LOG_INFO("Bond Management example started.");

    +    bool disabled_softdevice = false;^M
    +    if (nrf_sdh_is_enabled())^M
    +    {^M
    +      nrf_sdh_disable_request();^M
    +      while (nrf_sdh_is_enabled()) {}^M
    +      disabled_softdevice = true;^M
    +    }^M
    +    ^M
    +    if (disabled_softdevice)^M
    +    {^M
    +      nrf_sdh_enable_request();^M
    +      while (!nrf_sdh_is_enabled()) {}^M
    +      disabled_softdevice = false;^M
    +    }^M
    +  ^M
         advertising_start(erase_bonds);

         // Enter main loop.

    as well as setting optimization to O0.

    The program then crashes in main.c advertising_start because ble_advertising_start returns code 0x3001.

    However, I would expect that this line

    while (!nrf_sdh_is_enabled()) {}

    prevents the program from advancing to advertising_start while the softdevice is still disabled.

  • Hi Andreas, 

    I think that better approach would be to use the sd_softdevice_disable and sd_softdevice_enable API. The nrf_sdh_disable_request will only disable the SD if all the observers acknowledge the request. I think that nrf_sdh_is_enabled() might evaluate to true while the SDH state is NRF_SDH_EVT_STATE_DISABLE_PREPARE so the while loop might be exited prematurely.

    Best regards

    Bjørn 

Related