Error 13313 [Unknown error code] BLE cannot re-connect after disconnection

Hi, I'm using nRF52805. 

My BLE code could connect & communicate data perfectly for the first time. After the disconnection, I can still see the signal. However, when I try to reconnect it, the following error pops up. And I can never see the BLE signal again. I think the entire code stops running. 

// In the debugging mode: 

<info> app: BLE_GAP_EVT_CONNECTED
<error> app: ERROR 13313 [Unknown error code] at D:\StevenW\SDK_Code\example\Steven\20210922 eBTR_BLE_BPM_TV Btn v1\main.c:2075
PC at: 0x0001E849
<error> app: End of error report

This are my codes at line 2075

ret_code_t err_code_ble_nus;
err_code_ble_nus = ble_nus_data_send(&m_nus, nus_string, &bytes_to_send, m_conn_handle);
if ((err_code_ble_nus != NRF_ERROR_INVALID_STATE) && (err_code_ble_nus != NRF_ERROR_NOT_FOUND))
{
APP_ERROR_CHECK(err_code_ble_nus); // Line 2075
}


After Googleing, many people mentioned the same reason & solution (see link 1, link 2, link 3), and their solution is to add the following codes: 

case BLE_GATTS_EVT_SYS_ATTR_MISSING:
    err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0);
    APP_ERROR_CHECK(err_code);
    break;

However, this solution doesn't work for me. Any other ideas, please?

Thanks in advance! 

  • Hi, 

    Are you using Bonding?

    Does the central enable notification/indication before you can send the data?

    13313 is the same as BLE_ERROR_GATTS_SYS_ATTR_MISSING. You can read about this error code e.g. in this post

    Regards,
    Amanda

  • Thanks for your support, Amanda. 

    No, I'm NOT using bonding. Yes, I have read the link that you provided and many other links for BLE_ERROR_GATTS_SYS_ATTR_MISSING issue. Their solution is to add the BLE_ERROR_GATTS_SYS_ATTR_MISSING  to the following code section: 

    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("BLE_GAP_EVT_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);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("BLE_GAP_EVT_DISCONNECTED");
                // LED indication will be changed when advertising starts.
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_PHY_UPDATE_REQUEST");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                NRF_LOG_INFO("BLE_GAP_EVT_SEC_PARAMS_REQUEST");
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                NRF_LOG_INFO("BLE_GATTS_EVT_SYS_ATTR_MISSING");
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                NRF_LOG_INFO("BLE_GATTC_EVT_TIMEOUT");
                // Disconnect on GATT Client timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                NRF_LOG_INFO("BLE_GATTS_EVT_TIMEOUT");
                // Disconnect on GATT Server timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                NRF_LOG_INFO("BLE_DEFAULT");
                // No implementation needed.
                break;
        }
    }
    

    However, I already did it. What I found is: 

    1) If I just connect, and use Nordic UART Service, doesn't enable Tx Characteristic (i.e. mobile phone doesn't receive data from nRF52805), I can always connect & disconnect successfully. 

    2) If I enabled Tx Characteristic, for the 1st connection, everything is fine. After disconnection, and I re-connect, the ERROR 13313 will pop up (BLE_ERROR_GATTS_SYS_ATTR_MISSING). 

    3) Inside the ble_evt_handler() function, case BLE_GATTS_EVT_SYS_ATTR_MISSING is never reached. I used NRF_LOG_INFO() to print a message if case BLE_GATTS_EVT_SYS_ATTR_MISSING is reached. 

    Do you have any other clue, please? Thanks! 

  • Hi, 

    If you are not using Bonding, you could set it with sd_ble_gatts_sys_attr_set() when the sd_ble_gatts_hvx function returns BLE_ERROR_GATTS_SYS_ATTR_MISSING, e.g. as shown in this MSC.

    -Amanda

  • Thanks for your help, Amanda. 

    I solved the issue by using following code: 

    bytes_to_send = sprintf(nus_string,"%.3f", ble_test_data);
    
    ret_code_t   err_code_ble_nus;
    err_code_ble_nus = ble_nus_data_send(&m_nus, nus_string, &bytes_to_send, m_conn_handle);
    
    if (err_code_ble_nus == BLE_ERROR_GATTS_SYS_ATTR_MISSING){
        uint32_t err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
        APP_ERROR_CHECK(err_code);
        NRF_LOG_INFO("Case 1: Notification Disabled ===================================");
    }else if( (err_code_ble_nus != NRF_ERROR_INVALID_STATE) && (err_code_ble_nus != NRF_ERROR_NOT_FOUND) ){ 
        APP_ERROR_CHECK(err_code_ble_nus);
        NRF_LOG_INFO("Case 2");
    }else{
        NRF_LOG_INFO("Case 3");
    }

    Initially, when there is no "if statement" for "BLE_ERROR_GATTS_SYS_ATTR_MISSING", the APP_ERROR_CHCK() in case 2 will stop the entire program. 

    I have a follow-up question: When BLE_GATTS_EVT_SYS_ATTR_MISSING, the following code should execute and print "BLE_GATTS_EVT_SYS_ATTR_MISSING". However, I didn't see the printing "BLE_GATTS_EVT_SYS_ATTR_MISSING" at all.

    I can see the printing result "BLE_GAP_EVT_CONNECTED", "BLE_GAP_EVT_DISCONNECTED" and "BLE_DEFAULT" as expected. 

    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("BLE_GAP_EVT_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);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("BLE_GAP_EVT_DISCONNECTED");
                // LED indication will be changed when advertising starts.
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_INFO("BLE_GAP_EVT_PHY_UPDATE_REQUEST");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                NRF_LOG_INFO("BLE_GAP_EVT_SEC_PARAMS_REQUEST");
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                NRF_LOG_INFO("BLE_GATTS_EVT_SYS_ATTR_MISSING");
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                NRF_LOG_INFO("BLE_GATTC_EVT_TIMEOUT");
                // Disconnect on GATT Client timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                NRF_LOG_INFO("BLE_GATTS_EVT_TIMEOUT");
                // Disconnect on GATT Server timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                NRF_LOG_INFO("BLE_DEFAULT");
                // No implementation needed.
                break;
        }
    }

    Thanks in advance! 

Related