Peripheral missing disconnect on timeout

When communication fails on NRF connectivity dongle (In Python via pc_ble_driver) and Error code: NRF_ERROR_BUSY is received on attempts to write and one restarts python script, a timeout appears to occur in peripheral. the connection changes state (after delay) from BT_CONN_CONNECTED to BT_CONN_DISCONNECT_COMPLETE.

This does not trigger a callback and application thus does not know to call bt_conn_unref() thus advertising is not resumed.

System runs Zephyr on nRF Connect SDK 1.8.0 as peripheral only.

Parents Reply Children
  • Yes, and it works normally most of the time.

    Once in a while we get this odd situation where something happens after a while and the connection changes state. Then it no longer advertises, and link is no longer up. Trying to call on disconnect has no effect, and trying to start advertising returns 0 while not starting advertising.

  • When debugging I notice that disconnect does not work as it returns that it is not connected, but conn->ref is not 0. Calling unref till it reaches 0 causes it to start advertising again.

    But upon trying to connect to this we get
    ***New connection: 0 (printed by on_gap_evt_connected in our script)
    connect_to_device error: 'NoneType' object is not subscriptable.

    After this, it stops advertising again while state remains in BT_CONN_CONNECT_ADV.

  • Looks like, when the error happens, ref is still 3.
    Normally ref is 2, and upon disconnect we unref the local pointer to the connection and it returns to 1, and advertising is resumed. Are we using the bt_conn_ref() correctly?

  • Hi,

    Kyrre Aalerud said:
    when the error happens, ref is still 3.
    Normally ref is 2,

    That sounds strange. Where are the places you call bt_conn_ref() and bt_conn_unref() ? In what callbacks?

    Could you post the code relevant functions / callbacks where you call bt_conn_ref/bt_conn_unref ?

  • The ref:

    static void connected(struct bt_conn *conn, uint8_t err)
    {
        struct bt_conn_info info;
    
        if (err) 
        {
            LOG_ERR("BLE Connection failed (err 0x%02x)", err);
            return;
        }
    
        default_conn_ble = bt_conn_ref(conn);
    
        bt_conn_get_info(conn, &info);
        LOG_INF("BLE Connected: Interval=%d, Datalen=%d", info.le.interval, info.le.data_len->tx_max_len);
    

    The connected() callback goes on to check some parameters and request changes in data length if appropriate.


    The unref:

    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
        LOG_WRN("BLE Disconnected (reason 0x%02x)", reason);
        if (auth_conn) 
        {
            bt_conn_unref(auth_conn);
            auth_conn = NULL;
        }
        
        if (default_conn_ble) 
        {
            bt_conn_unref(default_conn_ble);
            default_conn_ble = NULL;
            disable_reporting_over_ble(); // Once disconnected, disable reporting over BLE
        }
    }

Related