Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Use NUS Service on bonded devices without discovery

Hi,

I am developing a system with 2 nrf52840 devices, communicating via the NUS Service. I am programming both the central and peripheral project. I am using the NRF5 SDK with S140 Softdevice on both sides.

I am trying to speed up the connection procedure as far as possible. Therefore, I bond both devices. I know that characteristics, that are notified on bonded devices, stay notified the next time they connect. It seems to work, since I can skip "ble_nus_c_tx_notif_enable()" for bonded device and still receive value notifications on the TX characteristic. However, the NUS event handler is not called before I call "ble_nus_c_on_db_disc_evt()".

The problem is that characteristic discovery takes to long for my application. Thus, I would like to directly start communicating with bonded devices, without discovery. Is there a way to do that? Do I have to call  ble_nus_c_on_db_disc_evt with the parameters read from the peer manager (e.g. by using pm_peer_data_remote_db_load()).

Thank you and best regards

Bjoern

Parents Reply Children
  • Hi, did you forget to add a link to your comment?

    I finally found the problem. I still don't know exactly how to fix this, though. It seems that sending data is blocked by an ongoing ATT_MTU exchange. I attached the trace log from my peripheral device:

     

    <info> app: Fast advertising.<\r><\r><\n>
    <info> app: Advertising started<\r><\r><\n>
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change<\r><\r><\n>
    <info> app: BLE_NUS_EVT_COMM_STARTED, start sending data<\r><\r><\n>
    <info> app: Data Sent Result = 8<\r><\r><\n>
    <info> app: BLE_GAP_EVT_CONNECTED: min_int: 6 max_int: 6, latency: 0, timeout: 400<\r><\r><\n>
    <info> app: Data Sent Result = 8<\r><\r><\n>
    <info> app: Data Sent Result = 8<\r><\r><\n>
    <info> peer_manager_handler: Connection secured: role: Peripheral, conn_handle: 0, procedure: Encryption<\r><\r><\n>
    <info> peer_manager_handler: Peer data updated in flash: peer_id: 0, data_id: Peer rank, action: Update, no change<\r><\r><\n>
    <info> app: Data Sent Result = 8<\r><\r><\n>
    <info> app: GATT ATT MTU on connection 0x0 changed to 247.<\r><\r><\n>
    <info> app: Data Sent Result = 0<\r><\r><\n>
    <info> app: BLE_NUS_EVT_TX_RDY<\r><\r><\n>
    <info> app: Data Sent Result = 0<\r><\r><\n>
    <info> app: BLE_NUS_EVT_TX_RDY<\r><\r><\n>
    <info> app: Data Sent Result = 0<\r><\r><\n>
    

    What I do, is starting to send data as soon as I receive the BLE_NUS_EVT_COMM_STARTED event from the NUS module. Data is sent in 20 ms Interval.

    I would expect to receive a BLE_NUS_EVT_TX_RDY event right after sending that first data package. However, this event is received more than 100 ms after my first attempt to send data. I also logged the answer I receive from ble_nus_data_send. The function always returns 8, which is "NRF_ERROR_INVALID_STATE", for my firsts attempts.  

    It seems that shortly after receiving the GATT event NRF_BLE_GATT_EVT_ATT_MTU_UPDATED,  ble_nus_data_send returns 0 and data is transferred.

    I looked deeper in the code of ble_nus_data_send and I can say for sure, that the following if statement never evaluates to true. 

        if (!p_client->is_notification_enabled)
        {
            return NRF_ERROR_INVALID_STATE;
        }

    Thus, "return NRF_ERROR_INVALID_STATE" is skipped from the first time, I call the function. Instead, sd_ble_gatts_hvx, which is called at the end of ble_nus_data_send, seems to return the error code 8. I looked to the API reference of sd_ble_gatts_hvx, which may return NRF_ERROR_INVALID_STATE, if "An ATT_MTU exchange is ongoing". 

    To make sure that this really is the problem, I did set NRF_SDH_BLE_GATT_MAX_MTU_SIZE to the default value of 23 on peripheral and central side. Before it was 247. This did speed up the connection process massively. Now ble_nus_data_send directly returns 0 after the characteristic has been notified, and I do not receive "NRF_BLE_GATT_EVT_ATT_MTU_UPDATED" anymore. I can now connect, encrypt and send data from peripheral to host within about 70 to 80 ms. This would satisfy my needs in theory but skipping the MTU update is not really an option, since I want to maximize throughput, which is hard with an MTU size of 23. Is there a way store the MTU size for bonded devices, so that both devices do not need to negotiate the MTU size on each connection?

    Best regards

    Björn 

Related