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

debugging sd_ble_gatts_hvx

Hi

I am trying to get to the bottom of a problem I am having with sending a buffer of data on connection and indication enable. Here's what I do: I have a process running, which is capturing sensor data every 10 seconds, and keeping it in a circular buffer. When a master connects, I want to send the circular buffer to the master app. I am doing that by triggering on the event that the CCCD is written to enable indications (I am using indication because I want to make sure that the values end up in the app). When this CCCD write is happening, I send the first item in my circular buffer, and then use the BLE_GATTS_EVT_HVC event to see if I have gotten a confirmation, just as in the health thermometer example.

I am running into a number of problems

  • when I trigger on the CCCD write and immediately do a sd_ble_gatts_hvx, I get an error 8 (illegal state); if I start a timer and do the same after 10 ms, then it is ok
  • I sometimes also have a BLE_ERROR_GATTS_SYS_ATTR_MISSING error, how can I avoid that? when should I normally do a sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0) (i do not use bonding)

I have the impression that timing issues or race conditions are causing my problems, can anyone give me hint on how to solve this?

  • Are you checking that the write event actually hits the CCCD of the characteristic you are trying to indicate, and that the value of the write has the indicate bit set? (It is the 2nd bit, so values 0x02 and 0x03 are both good). You should only get SYS_ATTR_MISSING if the BLE stack does not know the value of the CCCD, which is why I suspect that something else is written to.

    You should call sys_attr_set() immediately when connected, and just set it to NULL if you never bond.

  • Yes I am checking this. But I did not do a sd_ble_gatts_sys_attr_set when connecting, only when getting an BLE_GATTS_EVT_SYS_ATTR_MISSING event. Should I do this also on an BLE_GAP_EVT_CONNECTED soft device event then?

  • Yes, the best time to set it is immediately after connection. It is not until you actually connect that you know if this device is a known device or not, and the peer expects the GATTS CCCD/SCCD states to be preserved between connections. On connection, all CCCD states have value "?", and the BLE_GATTS_EVT_SYS_ATTR_MISSING event should only occur if a) the peer tries to read a CCCD state that is "?" or b) the stack tries to do an operation that depends on the state of the CCCD (indicate/notify) when the value is "?". A write will not trigger this, because the "?" value is just overwritten then.

  • I do not get the SYS_ATTR_MISSING anymore, but I do get an illegal state error when trying to do a sd_ble_gatts_hvx when I get a write event to the CCCD and value equals 2. Why is that? Is this because I do it in the call back function/event handler of the event? Should I schedule a new event from that, and then do a sd_ble_gatts_hvx?

  • The stack event is generated after the value has been received and stored, so there should be no issues with race conditions or calling this from the handler (unless you call it multiple times with no HVC, which you say you already check, which is good!). But if you ever got the BLE_ERROR_GATTS_SYS_ATTR_MISSING error, it means that you tried to indicate/notify some char who's CCCD cannot have been written to yet. I suspect that the peer is enabling all CCCDs, and by waiting a bit it enables the CCCD of the char you want to indicate.

Related