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

Calling sd_ble_gatts_hvx in radio notification

FormerMember
FormerMember

Hey everyone, I'm trying to send a value as a notification packet from GATT Server (slave) to GATT client (master) at 7.5 ms connection interval. I have set up the radio notification IRQ (SW IRQ) to fire before the radio becomes active at low IRQ priority. In this routine I call the sd_ble_gatts_hvx() routine. Without the sd_ble_gatts_hvx call, I get 7.5 ms interval. But with the call I get 15 ms routine.

void RADIO_NOTIFICATION_IRQHandler(void){
      //sd_ble_gatts_hvx call to send a notification
}

Is there a way send a GATT notification packet from the RADIO_NOTIFICATION_IRQHandler while still having 7.5 ms connection interval with S110 SD?

Edit: Adding that I have checked with different 'radio notification distances', from 800 us to 3260 us.

Edit 2: This behaviour is consistent even with 10 ms, 15 ms or 250 ms connection interval. I.e. the interval at which the radio notification event happens doubles when sd_ble_gatts_hvx is called in the radio notification IRQ handler.

Edit 3: Added a minimal example that has the problem mentioned in the comments.main_notify_radio_evt.c

Edit 4: Added a sniffer trace of how the notifications are sent.Sniffer_Trace.png

Edit 5: Added a small flow diagram to explain a comment. SendingGoodies.jpg (It'll be nice to add pics to comments) Setup: nrf51 DK with S110 v8.0.0 in connection with nrf51 DK S120 v2.1.0. Compiled with GCC in Linux. Thanks!

  • FormerMember
    0 FormerMember in reply to Susheel Nuguru

    Hi Hung,

    There are few setups that I've tested:

    1. S110 slave and S120 master on PCA10028 both with hardcoded max and min conn interval of 7.5 ms
    2. S110 with 7.5 ms max and min conn interval and S120 with 7.5 ms min conn interval and 30 ms max conn interval. In this I call sd_ble_gap_conn_param_update(m_conn_handle,0); right after connection establishment. I wait for BLE_GAP_EVT_CONN_PARAM_UPDATE before sending notification packets as shown in the second comment to the original question.
    3. Same as above with an Android phone as master instead of S120.

    In all the cases the notification packets are received at an interval of 15 ms. Please note that I check that I wait for BLE_EVT_TX_COMPLETE event before calling sd_ble_gatts_hvx in the active signal radio notification handler.

    This application cannot work if the notification are only sent at 15 ms interval. Could you please look into this.

  • I think the issue was with how you call sd_ble_gatts_hvx. BLE_EVT_TX_COMPLETE is triggered at the end of an event if in that event, the TX packet (notification/write command) sents in the last event was acked.

    This means if you queue only one packet when BLE_EVT_TX_COMPLETE happens, you will have one connection event with one notification next connection event will be no notification (it's the conn event when you have the BLE_EVT_TX_COMPLETE event) and next with connection event with one notification (BLE_EVT_TX_COMPLETE will not come for this event, because there was no notification sent last event, BLE_EVT_TX_COMPLETE will come at the next event).

    I would suggest you to try testing by queue as much as possible data when you receive BLE_EVT_TX_COMPLETE, until the buffer is full. This way, you will make sure at any connection event, there will be something sent.

    A sniffer trace will really clarify what happens in the air (connection interval, notification latency) and explains everything.

  • FormerMember
    0 FormerMember in reply to Susheel Nuguru

    Your theory seems correct. We also thought so. It is confirmed by the sniffer screenshot I attached in the original question. Aryan seems to have got this working in his setup, even with checking if BLE_EVT_TX_COMPLETE event is called. Any theory on how to get that working? We're working on an application where the most recent sample needs to be sent. The reason why we can't queue up in the TX buffer is that we cannot remove from the buffer once a packet is added. So if I queue up because of the reliable nature of BLE, the buffer can only be updated once all the packets are sent. This can become a problem where there is wireless interference causing old samples being tried to be sent over and over.

  • As you already mentioned, the nature of BLE doesn't support realtime requirement. All packet will be transmitted I assume that you want to only update the latest sample on each connection interval, my suggestion for you is to try to keep track of the number of packet in the buffer by using the number of packet you queue, minus the number of packet sent reported in BLE_EVT_TX_COMPLETE. If in one BLE_EVT_TX_COMPLETE you have the number of packet in the buffer is full, you would need to queue at least 7 packets (if the max number of packet per connection interval is 6). This is to make sure you will have at least 1 packet to be sent in the connection after the next one. So that we will not get into the situation with one connection event with packet sent and one without.

    But anyway, it will have a 7.5ms latency because you can't have a packet sent immediately but will have to wait for the next connection interval.

  • FormerMember
    0 FormerMember in reply to Susheel Nuguru

    I've got it working to send at every conn event of 7.5 ms by queuing up to 2 packets. For now we'll settle for this. Thanks for all the help.

Related