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

BLE NUS CENTRAL not ready for comms after receiving BLE_NUS_C_EVT_DISCOVERY_COMPLETE

Hi

I have a modified version of the BLE_NUS Central sample which connects to my production board for production test purposes.

All works fine, and Rx and Tx comms passed to/from the UART to the RX and Tx characteristics of the custom service running on my peripheral.

My issue is that after the central gets BLE_NUS_C_EVT_DISCOVERY_COMPLETE, if I immediately try to perform a GATT_Write on the peripherals RX characteristic, the Central Hangs

 ble_gattc_write_params_t const write_params =
    {
        .write_op = BLE_GATT_OP_WRITE_CMD,
        .flags    = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE,
        .handle   = p_ble_nus_c->handles.nus_rx_handle,
        .offset   = 0,
        .len      = length,
        .p_value  = p_string
    };

    return sd_ble_gattc_write(p_ble_nus_c->conn_handle, &write_params);

If I run the exact same code a fraction of a second later, it succeeds.

After connection and discovery of my service (and after setting up Notify for the RX and TX characteristics), I need to inform my peripheral who it was that just connected - in this case 'ProductionTestBoard' 0x07. I do this via a protocol structure I use everywhere else in the product.

My question is, can I test wait for any other event, or test the softdevice to wait until it REALLY HAS connected to my peripheral? I tried the usual 'sleep' before the gattc_write to no avail.

Nigel

  • Hi Nigel,

    Could you try to check the return code from sd_ble_gattc_write() when it fails? The connection is established and the services should have been discovered at this point so not sure why it fails. Possible return values copied from the API documentation:

    * @retval ::NRF_SUCCESS Successfully started the Write procedure.
    * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
    * @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
    * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
    * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
    * @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied.
    * @retval ::NRF_ERROR_BUSY For write with response, procedure already in progress. Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry.
    * @retval ::NRF_ERROR_RESOURCES Too many writes without responses queued.
    * Wait for a @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event and retry.
    * @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.

  • HI,

    I guess that you have multiple GATT client at your central role.

    You can refer to the code ble_nus_c.c which I modified to use the tx_buffer_process to queue up the write request.

    https://github.com/jimmywong2003/nrf5-packet-error-rate-measurement-on-ble-connection/blob/master/sdk_mod/ble_nus_c/ble_nus_c.c 

  • Hi

    Annoyingly this turned out to be because on my central I had wrapped the BLE comms session back to the peripheral with a timeout (using the APP_TIMER_DEF macro). The timer does not call the completion routine when it expires, and thus does not set the flag to 'true' and my while loop after the sd_ble_gattc_write never exits: while (!fAckRxOnTxCharacteristicCompleted && !fBleTxRxTimerExpired) { }. I use the timer to time a transaction at my application layer - sending of data and receipt of an ACK from peripheral.

    Its a little odd, as I use the identical code to wrap many other comms operations with timers. I am assuming that the current interrupt level means that timers cannot be used here?

    This code is on a production test board, so I have simply removed the 'while'. The same timer code is wrapping all comms (BLE and SPI) on the peripheral where it works just fine. 

    Nigel

  • Hi,

    Glad to hear that you found the problem. 

    veletron said:
    Its a little odd, as I use the identical code to wrap many other comms operations with timers. I am assuming that the current interrupt level means that timers cannot be used here?

    The app timer uses interrupt priority 6 or 7 depending on SDK version and configuration, same applies for Softdevice events. However, I think it's best when you can avoid blocking functions in ISRs.

    Vidar  

Related