How do I size the App Scheduler to take advantage of NAKs from the SoftDevice?

This is a follow-up to my previous postI'm developing a BLE Peripheral application on the nRF52832 that uses NRF_SDH_DISPATCH_MODEL_APPSH to receive events from the SoftDevice. My application involves using some software-implemented elliptic-curve cryptographic computations in APP_IRQ_PRIORITY_THREAD, which can take up to 1.5 seconds to run.

I found that if I send enough Characteristic Writes while the nRF52832 is doing the ECC computations, I can cause one of two effects, based on how I've configured the size of the App Scheduler. If it is 50, app_sched_event_put() in SD_EVT_IRQHandler() returns NRF_ERROR_NO_MEM. If it is 60, then I instead see NAKs from the SoftDevice to the Central on my BT sniffer.

My understanding is that this is because if the SoftDevice can buffer more Writes than the App Scheduler, it will overflow the App Scheduler because it can enqueue events from an interrupt context. However, if the App Scheduler is large enough, it will be able to handle all the events from the SoftDevice, and because the ECC computations are preventing another call to nrf_sdh_evts_poll(), the SoftDevice's internal buffers will fill, so it will start to NAK Writes from the Central.

I would like to be able to rely on the NAK behavior, so I need non-experimental reasoning for why there is this change in behavior between the App Scheduler sizes of 50 and 60. What is the maximum number of events that the SoftDevice could buffer from BLE because of, say, a malicious Central?

I am using s132 v5.1.0.

  • Hi,

    I would like to be able to rely on the NAK behavior, so I need non-experimental reasoning for why there is this change in behavior between the App Scheduler sizes of 50 and 60.

    Why you see a difference between a scheduler size of 50 and 60 is impossible to say without excellent knowledge and understanding your application and having properly analyzed it. The app scheduler is just a simple scheduler that is intended to transfer execution from interrupts to the main thread. This is useful in a lot of situations, but it does not in itself help you to process SoftDevice events or anything else faster (just at a different priority).

    As Susheel explained in the other thread, the SoftDevice will NACK packets if it's internal buffers are full, because it simply cannot store the data, so it must be dropped. In other words, data come in faster than they are processed by your application. To remedy this you will need to either reduce the amount of data received, or reduce the processing time so that you are able to handle the events in a due manner.

    If reducing the amount of data is not an option, you will need to do some optimization of your application in order to handle more incomming data. The app scheduler could perhaps be useful in this regard if you need to move things to a lower priority, but it is no magic bullet. I do not know anything about your application, but it could very well be that it does something that is not Bluetooth related at all that sue a lot of CPU time, and that is causing the problem. If this is the case (which is just an example really so it might not be) and data received is bursty, and you can delay the other CPU intensive tasks, you could perhaps just delay those operations. There is unfortunately no generic solution to this, and you have to look at your application as a whole.

    What is the maximum number of events that the SoftDevice could buffer from BLE because of, say, a malicious Central?

    I did not get this question. Can you elaborate? If you mean how many packets it can receive in a connection and buffer before it is handled by the application, that is 6 packets. This is a design choise of the SoftDevice and it cannot be configured to a higher number.

  • excellent knowledge and understanding your application

    I am willing to elaborate on or characterize any relevant parameters.

    app scheduler is just a simple scheduler

    Yes, which is why I believe we should be able to come to an answer.

    the SoftDevice will NACK packets if its internal buffers are full, because it simply cannot store the data, so it must be dropped

    The key change in behavior is that NAK'd packets are not "dropped" in the strictest sense. They are kept within memory on the Central, who would keep retrying to send the packet. If the App Scheduler overflows (the NO_MEM case), the only choices would be to really "drop" the packet or do some other error handling.

    If you mean how many packets it can receive in a connection and buffer before it is handled by the application, that is 6 packets.

    Then why do my sniffer captures appear to imply that the SoftDevice absorbed 45 packets here?

  • Elias said:
    Then why do my sniffer captures appear to imply that the SoftDevice absorbed 45 packets here?

    I assume your application was able to process most of the events?

  • My application is able to process all the events, but not until after that span of NAKs. During the indicated 45 packets and the NAKs, my application is performing ECC computations, and is therefore unable to immediately continue with nrf_sdh_ble_evts_poll() to process the events.

  • I see. Without knowing the details of your application then, it seems sensible to try to make sure the ECC computations (and any other non-time-critical but CPU intensive operations) have lower priority than anything else.

    The problem here is that the apps scheduler is very simple without any concept of priorities so it will not help you with this, unless if you only use the apps scheduler for these tasks (and then use a different method for SoftDevice events). You could try that, but depending on your application that may cause other problems and not be a good idea.

    This sound like a typical issue where an RTOS would have made things simpler, as you could have your ECC computations in a thread with lower priorities than all other threads. So that could also be something to consider Not necessarily migrating to an RTOS as that can have big implications in itself, but based on what you write it seems like you need to find a mechanism to ensure that ECC handling is given the lowest priority, in some way that works for your application.

Related