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 Reply Children
  • 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

Related