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

Issue with sd_ble_gap_disconnect

Hello everybody

I hit another issue with sd_ble_gap_disconnect.

The short story is this one. I want the peripheral to initiate a disconnect if no activity for a predefined interval. At this moment, for test purpose only, i just implemented a timer which triggers sd_ble_gap_disconnect 5sec after the connect event. So i have my application running on a 52810 board. I use nrfConnect to connect to the device and the device triggers disconnect 5 sec after. After disconnect event i reconnect manually again to the device in nrfConnect. The log captured in the console shows like this

[00:00:00.000,000] <info> app_timer: RTC: initialized.
[00:00:00.000,000] <info> app: Ble tutorial started.
[00:00:00.000,000] <info> app: on adv_evt - evt = 3
[00:00:00.000,000] <info> app: Fast advertising.
[00:00:00.000,000] <info> app: Connected to a previously bonded device.
[00:00:00.000,000] <info> app: BLE event received. Event type = 16

[00:00:00.000,000] <info> app: Connected.
[00:00:00.454,162] <info> app: BLE event received. Event type = 18

[00:00:00.717,834] <info> app: BLE event received. Event type = 18

[00:00:04.967,285] <info> app: on adv_evt - evt = 3
[00:00:04.967,285] <info> app: Fast advertising.
[00:00:04.967,285] <info> app: BLE event received. Event type = 17

[00:00:04.967,346] <info> app: Disconnected.
[00:00:04.967,346] <info> app: Connected to a previously bonded device.
[00:00:04.967,346] <info> app: BLE event received. Event type = 16

[00:00:04.967,346] <info> app: Connected.
[00:00:05.447,326] <info> app: BLE event received. Event type = 18

[00:00:05.714,721] <info> app: BLE event received. Event type = 18

[00:00:09.967,346] <error> app: ERROR 8 [NRF_ERROR_INVALID_STATE] at C:\dev\52810\nRF5_SDK_17.0.2_d674dde\examples\ble_peripheral\ble_app_empty\main.c:338
PC at: 0x0001F429
[00:00:09.982,727] <error> app: End of error report

As you can see there is a first Disconnect event but the second one is missing because the device crashes and it shows the error report with error code = 8 which is invalid parameters

Digging further, the crash happens in in send_update_request when calling sd_ble_gap_conn_param_update because the second parameter p_new_conn_params is totaly invalid. Soething happen when pushet to the stack. SP = 20005f40 which is reasonable

In caller function update_timeout_handler the p_instance variable has valid values, but somehow when calling send_update_request the address is changed from 20002d8c+8 (how it is shown in update_timeout_handler) to 3ff00000 and this wrong value is pushed on the stack

Here is the call stack (hope you can access the link)

the way i call sd_ble_gap_disconnect is this one:

  - i instantiated a timer in main with time_ms = 5000 

 

const nrf_drv_timer_t INACTIVITYTIMER = NRF_DRV_TIMER_INSTANCE(1);
...
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
err_code = nrf_drv_timer_init(&INACTIVITYTIMER, &timer_cfg, inactivity_timer_evt_handler);
...
time_ticks = nrf_drv_timer_ms_to_ticks(&INACTIVITYTIMER, time_ms);
nrf_drv_timer_extended_compare(&INACTIVITYTIMER, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);

In ble_evt_handler on connect/disconnect events i start/stop the timer

 switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected.");
            err_code = bsp_indication_set(BSP_INDICATE_DISCONNECTED);
            APP_ERROR_CHECK(err_code);
            nrf_drv_timer_disable(&INACTIVITYTIMER);
            board_state = DISCONNECTED;
            break;

        case BLE_GAP_EVT_CONNECTED:
            NRF_LOG_INFO("Connected.");
            err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
            APP_ERROR_CHECK(err_code);
            m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
            APP_ERROR_CHECK(err_code);
            nrf_drv_timer_enable(&INACTIVITYTIMER);
            board_state = CONNECTED;
            break;

And finally in the timer callback, sd_ble_gap_disconnect is invoked

 switch (event_type)
    {
    case NRF_TIMER_EVENT_COMPARE0:
      if (board_state == CONNECTED && m_conn_handle != BLE_CONN_HANDLE_INVALID)
        {
        sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
        }

The environment i use is segger studio and sdk 17.02

The issue happens randomly after 2 to 20 manual reconnects

What am i doing wrong?Frowning2

  • Hi Viorel, 
    You can reduce the FIRST_CONN_PARAMS_UPDATE_DELAY to something lower than 5 seconds. This will reduce the chance that you have you connection interval request at the same time as disconnection request. 

    Another thing you can do is to ignore the NRF_ERROR_INVALID_STATE if you are calling disconnecting. You can check in conn_params_init() that's where the error_handler is assigned. Go to that error_handler and add the code to ignore if the error_code is NRF_ERROR_INVALID_STATE . 

  • Hi Hung

    thx for the answer.

    Yes in case disconnect is triggered by the application the solution is ok, but in case disconnect is triggered by the remote device it doesnt work. The question which comes to my mind is if it is safe to ignore NRF_ERROR_INVALID_STATE. 

    Would that be possible that sd_ble_gap_conn_param_update return value to tell the caller the action cannot be completed because a disconnect is in progress e.g. NRF_ERROR_BUSY, or...

  • The question which comes to my mind is if it is safe to ignore NRF_ERROR_INVALID_STATE

    That depends on your application!

    The error tells you, "this call did nothing, because the system is in the wrong state".

    • In your case, it seems you didn't want it to happen anyhow - so no harm done
    • If, however, you thought you should have been in the right state, and you did want it to happen - then you're going to have to take some recovery action.

    This is really just about software design - not particularly specific to Nordic.

  • The setup is this one: i have my nrf52810 device connected with a remote device which is my phone.

    If i trigger disconnect from the app on my 52810 and get into a NRF_ERROR_INVALID_STATE i can check if disconnect is in progress but not completed and can ignore  Its a transient state

    If i trigger a disconnect from my pone and get into an invalid state on nrf52810 i have no clue if there is a disconnect in progress but not completed. So can i ignore it? Better would be if i can get some information from SD and this points to Nordic.

  • Hi Viorel, 
    No, there isn't an issue if the connection is disconnecting and you call sd_ble_gap_conn_param_update () before it's actually disconnected and you get NRF_ERROR_INVALID_STATE. The softdevice would simply ignore the command and proceed to disconnect. It's fine to ignore NRF_ERROR_INVALID_STATE error from sd_ble_gap_conn_param_update (). 

Related