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.

  • Simple question that's not so simple - How does one invoke a sleep as you reference in this system?

  • Now that just adds to the confusion. I have long looked at this function as a hopeful solution to many problems but I have never been able to understand what an 'application event'  was. In most contexts that I have worked in, 'application' is what I write on top of an SDK. But if that is true, I would expect I could define an event but I cannot. So how do I wake this thing up? Once called does it wake on every event such as a BLE_GATTS_EVT_WRITE?

    Also, enumerations like BLE_GATTS_EVT_WRITE are events, not interrupts as I understand it. Well they are are called events. Maybe not? When I receive a GATTS or GAP event, am I back on the main context? Or am I only in the main context if I am in the main function? So am I forced to be that for loop which is now occupied by the 'power_manage()' method?

    If I were sending notifications instead of indications would it still be so complicated? Many vendors send sequences of data but I don't know if they use Nordic chips. But they also use notifications instead of indications.

  • As stated in the API documentation for sd_app_evt_wait(), an application event is either an application interrupt or a pended interrupt when the interrupt is disabled. An example of this is when the RTC1 interrupt gets triggered inside the app_timer module. This interrupt would then make your program return from the sd_app_evt_wait() function.

    brianreinhold said:
    Also, enumerations like BLE_GATTS_EVT_WRITE are events, not interrupts as I understand it.

     Yes, you've understood it correctly. These are internal Softdevice events.

    The Softdevice triggers the SOFTDEVICE_EVT_IRQ interrupt to let the application know when new Softdevice events are available, and the application will then retrieve the the events by calling  sd_evt_get() and sd_ble_evt_get() while still inside the Softdevice interrupt handler.

    brianreinhold said:
    If I were sending notifications instead of indications would it still be so complicated? Many vendors send sequences of data but I don't know if they use Nordic chips. But they also use notifications instead of indications.

    Notifications are a bit easier to deal with as you can queue up multiple notifications at a time. Though, instead of handling busy errors, you will have to handle the NRF_ERROR_NO_TX_PACKETS error if the notification output queue becomes full.

    Also, I took a screenshot from Keil to try illustrate how Softdevice events are being propagated to the on_ble_evt() handler from the Softdevice interrupt. Let me know if you have questions to this.

    on_ble_evt() invoked in interrupt context:

  • It's still not clear to me what an application event is. As I stated I hoped that I could use this wait() to replace a semaphore.

    If I have something like this (the power_manager() has the sd_app_evt_wait() )

        for (;;)
        {
            if (NRF_LOG_PROCESS() == false)
            {
                my_command_handler();
                power_manage();
            }
        }

    what events would cause 'my_command_handler' to be called? Would a BLE_GATTS_EVT_WRITE cause the sd_app_evt_wait() to return? Is BLE_GATTS_EVT_WRITE an Application event? If so that would be great (as long as the event handler that I have initialized with the soft device gets called first).

    I have read the docs on these methods over and over again but there were so many things (like application events) that I just could not figure out what was meant.

    It would be SOOO helpful if someone would say exactly what an 'application' event is. I write the application, but I clearly do not define these events. Are application events ALL events received by the application? In the docs they talk about SoftDevice events and don't call them application events. So what is the story?

Related