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

sd_ble_gap_disconnect returns success but BLE_GAP_EVT_DISCONNECTED event doesn't happen until a while later. A conn_params_error happens during this period.

I'm using S112 and SDK 14.2 to target NRF52810, but using the PCA10040 DK for now. 

I've been coming back this issue multiple times over the past couple of months, still unable to find any hints online. This intermittent issue seems to happen maybe 1 in 10-15 times when disconnecting from my Android device. My firmware needs to handle all kinds of broken Android Bluetooth implementations on all devices (and iOS) so I'm not worrying about device specifics at the moment, just how to deal with weird situations like this in the firmware. 

Normal procedure:

  1. App searching for NRF device
  2. Press button on DK to start advertising
  3. Connection
  4. Read/write some characteristics
  5. sd_ble_gap_disconnect() returns 0
  6. BLE_GAP_EVT_DISCONNECTED event
  7. All ok

When it breaks: 

  1. App searching for NRF device
  2. Press button on DK to start advertising
  3. Connection
  4. Read/write some characteristics
  5. sd_ble_gap_disconnect() returns 0
  6. Seems to hang around still connected (using too much power) for 2-5 seconds
  7. conn_params_error 8 (NRF_ERROR_INVALID_STATE)
  8. Hangs around for another ~10 seconds using power
  9. Finally BLE_GAP_EVT_DISCONNECTED

I know the Bluetooth implementation on some Android devices is awful and my guess was that the phone is hanging onto the connection in the background (this happens too often), but if I turn off the phone's Bluetooth (reliably kills background connections) during step 8, it still takes many seconds before we hit step 9.

It seems the softdevice is failing to disconnect for some reason, the connection params update thinks the device is in an invalid state (probably looks like it is disconnected) but it hasn't really finished disconnecting. Any ideas what could be causing this to happen? 

Thanks in advance. 

  • Hi, the likely problem here is that if the ACK on the disconnect packet is lost (only 1 packet), then the softdevice will wait until supervisor timeout occurs for that specific connection until the disconnect event occurs. This is according to BLE specifications. There is not much that can be done here, other than possible change the connection supervisor timeout shortly before calling sd_ble_gap_disconnect() to reduce the time.

  • Hi Kenneth, thanks for the information. That seems to make sense, your workaround suggestion should do the trick. If this really is the problem then the softdevice probably shouldn't be attempting to update connection parameters during this period (and always failing) - possibly something to update. Thanks

  • Another update on this: the connection params error happens 7 seconds after connection, this is equal to my FIRST_CONN_PARAMS_UPDATE_DELAY. The BLE_GAP_EVT_DISCONNECTED event happens around 21 seconds after connection, or 18 seconds after sd_ble_gap_disconnect() is called. CONN_SUP_TIMEOUT is 2 seconds (MSEC_TO_UNITS(2000, UNIT_10_MS)), so now I'm not sure it is the connection supervisor forcing the disconnect to finish... Something different is going on here which is taking much longer than the supervisor would. 

  • There may be some sort of race condition here, to easiest may just be to add some global flag to ensure that you don't call any connection parameter update after sd_ble_gap_disconnect()?

  • That would help stop that error event, yes. The real issue is this whole 18 seconds of high power between attempting to disconnect, and the actual event; this time is much longer than the supervisor timeout. I've just had a look using the power profiler and the current use over that long period starts with 1ms~ pulses slowly increasing linearly up to about 15ms long pulses of full CPU operation; it's a very strange feature, definitely looking more like a bug in the softdevice now I've seen this. Attached animated GIF of the power consumption (DCDC off) from sd_ble_gap_disconnect() to the event. 

    I would assume that a disconnect forced by the supervisor timeout doesn't expect a response from the connected device, but it seems that a user initiated disconnect using sd_ble_gap_disconnect() is able to get stuck if the other device happens to fail during that process. Note that during this period, other functions are still working normally, a pin interrupt followed by SPI transfer are able to work during this weird high power consumption period. 

Related