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

Stopping ble_conn_params.c's timers while supporting concurrent connections?

My Peripheral is using the ble_conn_params module. I'm seeing that if my Peripheral calls sd_ble_gap_disconnect() soon after making a connection, the module will sometimes throw NRF_ERROR_INVALID_STATE to ble_conn_params_init_t.error_handler. Is there a way to avoid this 100% of the time?

Inspecting the ble_conn_params.c code, it appears this is because the app_timer that is used to periodically send connection parameter update events is firing after sd_ble_gap_disconnect() is called, but before the SoftDevice has had a chance to complete the disconnection procedure.

I've considered using ble_conn_params_stop() after sd_ble_gap_disconnect(), but this would stop activity for all concurrent connections, instead of only the one connection that is to be terminated. Similarly, it looks like ble_conn_params_init() isn't designed to configure only one connection at a time. ble_conn_params_change_conn_params() also doesn't appear to provide a way to affect a currently running app_timer.

I'm using SDK 14.2, and the module in SDK 15.3 appears to be identical.

  • Hi,

    I do not immediately see from where you get NRF_ERROR_INVALID_STATE, but you can update the module to check for it after every sd_ble_* call, in the same way, that it does after sd_ble_gap_disconnect(), and ignore it if it occurs. I do not see any issues with it (though I might have overlooked something).

    Regarding using ble_conn_params_stop(), you are of course right that it will stop the conn_params module for all connections. However, you can make anew function similar to the existing ble_conn_params_stop() that you can provide a connection handle, and it will only stop that connection handle instead of looping through all (use instance_get() to get the instance for the relevant connection handle).

  • Let me make sure we agree on the issue. If I call ble_conn_params_change_conn_params() directly after sd_ble_gap_disconnect(), like this

      ret_code_t err_code = sd_ble_gap_disconnect(connHandle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
      APP_ERROR_CHECK(err_code);    
    
      err_code = ble_conn_params_change_conn_params(connHandle, &myConnParams);
      APP_ERROR_CHECK(err_code);

    the second function returns NRF_ERROR_INVALID_STATE. In the same way, the when module's app_timer fires between sd_ble_gap_disconnect() and the firing of BLE_GAP_EVT_DISCONNECTED, the error_handler is called with the same error.

  • Hi,

    Yes, I see. There are several ways of solving this, but I don't know exactly what you are after.

    For the first case, you should not call ble_conn_params_change_conn_params() in the first place after calling sd_ble_gap_disconnect(). You can also implement special handling of the NRF_ERROR_INVALID_STATE in your application so that you filter it out before calling APP_ERROR_CHECK or similar since you know what causes this. It is an invalid state, but you know you can simply ignore it.

    Elias said:
    In the same way, the when module's app_timer fires between sd_ble_gap_disconnect() and the firing of BLE_GAP_EVT_DISCONNECTED, the error_handler is called with the same error.

    The timeout handler can call sd_ble_gap_disconnect(), but in this case, it checks explicitly or NRF_ERROR_INVALID_STATE to filter tha out, so that is no problem. However, it can also call send_update_request() which in turn calls sd_ble_gap_conn_param_update(), which can return NRF_ERROR_INVALID_STATE. This is not handled explicitly. Filtering this out as well should solve this issue.

Related