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

How to send a sequence of indications?

I need to indicate a characteristic value that is longer than the MTU. Using the pc-ble-driver, no problem. Windows supports semaphores and I can call sd_ble_gatts_hvx(), wait on a semaphore, and release the semaphore in the BLE_GATTS_EVT_HVC event and then indicate the next hunk.

That doesn't work when you write code for the chip as the SDK and SoftDevice do not support semaphores or an equivalent to semaphore functionality in any form. So how does one indicate a characteristic value longer than the MTU? It may require a sequence of N indications to get all the data across.

I have tried the following:

call err_code = sd_ble_gatts_hvx() and if the err_code = NRF_ERROR_BUSY then call sd_ble_gatts_hvx() again until one gets success. If I replace the semaphore with this while loop in the pc-ble-driver, it works. However, when I do the same thing on the chip, I get the NRF_ERROR_BUSY and then it hangs. It seems one cannot repeatedly call this method when busy even though the documentation says you can. How can I solve this issue on the nRF51822?

I do not know if the problem persists on the nRF52840. My pc-ble-driver code is for the nRF52840 dongle where both semaphores and the busy loop work. I have not used the pc-ble-driver on a nrf51822 chip.

I put the method that sends the sequence of indications in a single-shot timer, called from the BLE_GATTS_EVT_WRITE event handler (the central peer writes commands to the peripheral to send data - no I do NOT want to have the peer do reads here!!!!). It helped a little bit in the sense I got three indications in the sequence sent but then it stopped.

Thanks for any solution to this problem.

  • Okay, I looked at the thread mode which I am doing or trying to do. However, it contradicts what I have read in the documentation. The docs say that I need to call the sd_ble_evt_get() until I drain all the queued events. That's not what I see in the message flow. The message flow says to call the sd_app_evt_wait() after the call with response NRF_SUCCESS.

    I am not doing that now (though things are still not working). Which is correct? cycle through the sd_ble_evt_get() and dispatch event until I get no more events OR call once, dispatch event, call sd_app_evt_wait and repeat?

  • Turns out all the issues I was having had nothing to do with indication sequences and handling of the sd_ble_evt_get().

    It was NRF_LOG_DEBUG. I guess I was trying to write an array of bytes converted to a HEX string that was too long. I do not know what the limit is, but commenting out that line of code solved the problem. Cost me a week and a half of hair pulling frustration.

    Was looking for answers in all the wrong places....

    So the approach I took where in the for(;;) loop I handle the sd_app_evt_wait()

    followed by the sd_ble_evt_get() with all its own loops but eventual dispatch on

    ble_evt_dispatch()

    I put the command handler in a one-short timer and set a flag if data needed to be indicated

    The indicate_data() method was in that main for(;;) loop. It would only get invoked if the flag was set.

    Though the final solution is VERY different than any of the health device examples it works. It might be good if you had an example which illustrated this kind of process. THough it is no semaphore; it accomplishes what a semaphore would have done. But it is much more like a basic embedded loop where you loop through, perform/handle one task, loop again and handle the next and so on.

Related