ble_app_uart_c example sd_ble_gap_disconnec function failure

Hi, I am running ble_app_uart_c example with a PCA10056 DK board. I modified the example to accept command from uart. Everything look OK. But when I tried to command the host to disconnect from peripheral by the following code:

err_code = sd_ble_gap_disconnect(conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
iAPP_ERROR_CHECK(err_code);

I got the following error:

<error> nrf_ble_gq: SD GATT procedure (1) failed on connection handle 0 with error: 0x00000008.
<error> app: Fatal error

Then the device got reset.

Any idea how to fix the issue? Thanks.

Parents
  • Hi.

    sd_ble_gap_disconnect() returning with err_code 08:

    NRF_ERROR_INVALID_STATE - Disconnection in progress or link has not beeen established.

    Which implies that you aren't actually in an active connection when the disconnection call is made. Could you verify that you are in a connection at the time you make a call to disconnect?

    Br,
    Joakim

  • Hi Jookim,

    Just some additional info. I tried PCA10040 board and got similar results. I used SDK nRF5_SDK_17.1.0. Thanks.

    Best Regards

    azjo 

  • Thank you!

    Maybe you can share your code? Or the relevant modifications you made?

    From where do you call the sd_ble_gap_disconnect() function?

    Br

    Joakim

  • Hi,

    Attached are my modifications:

    I define a global var uint16_t conn_handle. This var is assigned.a value at ble_evt_handler. The sd_ble_gap_disconnect function call is from uart_event_handle. Please let me know if you have any other questions. Thanks.

    BR

    azjo

    uint16_t conn_handle;

    void uart_event_handle(app_uart_evt_t * p_event)
    {
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint16_t index = 0;
    uint32_t ret_val;
    uint8_t target=0;

    switch (p_event->evt_type)
    {
    /**@snippet [Handling data from UART] */
    case APP_UART_DATA_READY:
    UNUSED_VARIABLE(app_uart_get(&data_array[index]));
    index++;

    if ((data_array[index - 1] == '\n') ||
    (data_array[index - 1] == '\r') ||
    (index >= (m_ble_nus_max_data_len)))
    {
    NRF_LOG_DEBUG("Ready to send uart data over BLE NUS");
    NRF_LOG_HEXDUMP_DEBUG(data_array, index);

    Store_Identify_Command_Buffer(&data_array[0], index);

    do
    {
    ret_val = ble_nus_c_string_send(&m_ble_nus_c, data_array, index);
    if ( (ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES) )
    {
    APP_ERROR_CHECK(ret_val);
    }
    } while (ret_val == NRF_ERROR_RESOURCES);

    index = 0;
    }
    break;

    /**@snippet [Handling data from UART] */
    case APP_UART_COMMUNICATION_ERROR:
    NRF_LOG_ERROR("Communication error occurred while handling UART.");
    APP_ERROR_HANDLER(p_event->data.error_communication);
    break;

    case APP_UART_FIFO_ERROR:
    NRF_LOG_ERROR("Error occurred in FIFO module used by UART.");
    APP_ERROR_HANDLER(p_event->data.error_code);
    break;

    default:
    break;
    }
    }

    void Store_Identify_Command_Buffer(uint8_t *data_array, uint8_t len)
    {
    if (1==Check_Input_Command(&data_array[0],&DISCONNECT_MODULE_ID[0],sizeof(DISCONNECT_MODULE_ID)-1))
    {
    if (conn_handle == BLE_CONN_HANDLE_INVALID)
    {
    printf("Invalid conn_handle\r\n");
    break;
    }
    err_code = sd_ble_gap_disconnect(conn_handle,
    BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (NRF_ERROR_INVALID_STATE != err_code)
    {
    APP_ERROR_CHECK(err_code);
    }
    }

    }

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
    ret_code_t err_code;
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);

    // start discovery of services. The NUS Client waits for a discovery result
    err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
    APP_ERROR_CHECK(err_code);

    printf("Gap Connected. conn_handle: 0x%x\r\n",p_gap_evt->conn_handle);

    conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    break;

    case BLE_GAP_EVT_DISCONNECTED:

    printf("Disconnected from conn_handle: 0x%x, reason: 0x%x\r\n",
    p_gap_evt->conn_handle,
    p_gap_evt->params.disconnected.reason);
    conn_handle = BLE_CONN_HANDLE_INVALID;//p_ble_evt->evt.gatts_evt.conn_handle;//p_gap_evt->conn_handle;
    break;

    case BLE_GAP_EVT_TIMEOUT:
    printf("BLE_GAP_EVT_TIMEOUT src:%d\r\n",p_gap_evt->params.timeout.src);
    if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
    {
    printf("Connection Request timed out.\r\n");
    }
    break;

    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
    // Pairing not supported.
    err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
    APP_ERROR_CHECK(err_code);
    break;

    case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
    printf("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST src:%d\r\n",p_gap_evt->params.conn_param_update_request.conn_params.conn_sup_timeout);
    // Accepting parameters requested by peer.
    err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
    &p_gap_evt->params.conn_param_update_request.conn_params);
    APP_ERROR_CHECK(err_code);
    break;

    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
    {
    printf("PHY update request.\r\n");
    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_GATTC_EVT_TIMEOUT:
    // Disconnect on GATT Client timeout event.
    printf("GATT Client Timeout.\r\n");
    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:
    // Disconnect on GATT Server timeout event.
    printf("GATT Server Timeout.\r\n");
    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;
    case BLE_GAP_EVT_ADV_REPORT:
    break;
    default:
    break;
    }
    }

    void uart_event_handle(app_uart_evt_t * p_event)
    {
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint16_t index = 0;
    uint32_t ret_val;
    uint8_t target=0;

    switch (p_event->evt_type)
    {
    /**@snippet [Handling data from UART] */
    case APP_UART_DATA_READY:
    UNUSED_VARIABLE(app_uart_get(&data_array[index]));
    index++;

    if ((data_array[index - 1] == '\n') ||
    (data_array[index - 1] == '\r') ||
    (index >= (m_ble_nus_max_data_len)))
    {
    NRF_LOG_DEBUG("Ready to send uart data over BLE NUS");
    NRF_LOG_HEXDUMP_DEBUG(data_array, index);

    Store_Identify_Command_Buffer(&data_array[0], index);

    do
    {
    ret_val = ble_nus_c_string_send(&m_ble_nus_c, data_array, index);
    if ( (ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES) )
    {
    APP_ERROR_CHECK(ret_val);
    }
    } while (ret_val == NRF_ERROR_RESOURCES);

    index = 0;
    }
    break;

    /**@snippet [Handling data from UART] */
    case APP_UART_COMMUNICATION_ERROR:
    NRF_LOG_ERROR("Communication error occurred while handling UART.");
    APP_ERROR_HANDLER(p_event->data.error_communication);
    break;

    case APP_UART_FIFO_ERROR:
    NRF_LOG_ERROR("Error occurred in FIFO module used by UART.");
    APP_ERROR_HANDLER(p_event->data.error_code);
    break;

    default:
    break;
    }
    }

    void Store_Identify_Command_Buffer(uint8_t *data_array, uint8_t len)
    {
    if (1==Check_Input_Command(&data_array[0],&DISCONNECT_MODULE_ID[0],sizeof(DISCONNECT_MODULE_ID)-1))
    {
    if (conn_handle == BLE_CONN_HANDLE_INVALID)
    {
    printf("Invalid conn_handle\r\n");
    break;
    }
    err_code = sd_ble_gap_disconnect(conn_handle,
    BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (NRF_ERROR_INVALID_STATE != err_code)
    {
    APP_ERROR_CHECK(err_code);
    }
    }

    }

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
    ret_code_t err_code;
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    err_code = ble_nus_c_handles_assign(&m_ble_nus_c, p_ble_evt->evt.gap_evt.conn_handle, NULL);
    APP_ERROR_CHECK(err_code);

    err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
    APP_ERROR_CHECK(err_code);

    // start discovery of services. The NUS Client waits for a discovery result
    err_code = ble_db_discovery_start(&m_db_disc, p_ble_evt->evt.gap_evt.conn_handle);
    APP_ERROR_CHECK(err_code);

    printf("Gap Connected. conn_handle: 0x%x\r\n",p_gap_evt->conn_handle);

    conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    break;

    case BLE_GAP_EVT_DISCONNECTED:

    printf("Disconnected from conn_handle: 0x%x, reason: 0x%x\r\n",
    p_gap_evt->conn_handle,
    p_gap_evt->params.disconnected.reason);
    conn_handle = BLE_CONN_HANDLE_INVALID;//p_ble_evt->evt.gatts_evt.conn_handle;//p_gap_evt->conn_handle;
    break;

    case BLE_GAP_EVT_TIMEOUT:
    printf("BLE_GAP_EVT_TIMEOUT src:%d\r\n",p_gap_evt->params.timeout.src);
    if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
    {
    printf("Connection Request timed out.\r\n");
    }
    break;

    case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
    // Pairing not supported.
    err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
    APP_ERROR_CHECK(err_code);
    break;

    case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
    printf("BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST src:%d\r\n",p_gap_evt->params.conn_param_update_request.conn_params.conn_sup_timeout);
    // Accepting parameters requested by peer.
    err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
    &p_gap_evt->params.conn_param_update_request.conn_params);
    APP_ERROR_CHECK(err_code);
    break;

    case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
    {
    printf("PHY update request.\r\n");
    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_GATTC_EVT_TIMEOUT:
    // Disconnect on GATT Client timeout event.
    printf("GATT Client Timeout.\r\n");
    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:
    // Disconnect on GATT Server timeout event.
    printf("GATT Server Timeout.\r\n");
    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;
    case BLE_GAP_EVT_ADV_REPORT:
    break;
    default:
    break;
    }
    }

  • Thank you.

    I'll look at your code and see what I can find.

    BR,
    Joakim

  • Hi Joakim,

    It looks the issue is caused by calling ble_nus_c_string_send after the connection is closed. The issue now is fixed.

    Thanks for your help,

    azjo 

  • Thanks for letting me know.

    Glad you found the issue.

    Thanks,
    Joakim

Reply Children
No Data
Related