Reentrancy with SDK15.3

I'm using SDK1.3 on a nRF52840 and running BLE on it.  I'm using FreeRTOS under it and specifically non-preemptive scheduling.  From time to time I do a scan using a filter of the names.

I've got a bug that acts more like a stack overrun (it isn't as far as I can tell) with some wild things happening when I have a LOT (like 40) of things that I'm searching for in the space.  If I have only a few things I'm looking for in the space, things are working fine.  I get callbacks from the SD that basically are giving me things like BLE_GAP_EVT_ADV_REPORT or (further downstream) NRF_BLE_SCAN_EVT_FILTER_MATCH which I'm catching and dealing with.

This is all coming back from a setup line:

    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);

where ble_evt_handler() sorts out a bunch of stuff...  Once we have the thing actually scanning it's sending back things through some other callbacks set up from the SDK calls.

So my question here is one of reentrancy and how these callbacks are actually working:

*) These are eventually being called by the soft device but I don't know in what context...   Are these essentially ISR level calls being made from the SD so that they are preemptive (i,.e. if I'm in the callbacks too long I'm going to get overrun by another)?

*) Can I use semaphores inside those callbacks so that I can hold off calls that are happening too often?

*) Can these callbacks in fact be overlapped or does the SD itself wait till it all comes back to it before sending another one?

Just asking questions to clarify my understanding of context here so I can go figure out what I need to do to defend myself...

Parents
  • *) These are eventually being called by the soft device but I don't know in what context...   Are these essentially ISR level calls being made from the SD so that they are preemptive (i,.e. if I'm in the callbacks too long I'm going to get overrun by another)?

    Yes, the callbacks triggered by the SoftDevice (e.g., ble_evt_handler) are indeed called from the SoftDevice's Interrupt Service Routine (ISR) context. The SoftDevice runs at a high interrupt priority level, so when it triggers an event (like BLE_GAP_EVT_ADV_REPORT), it is effectively running in an ISR. This means:

    Preemption is enabled: The SoftDevice can interrupt lower-priority tasks, but other ISRs with a higher priority than the SoftDevice ISR (like other critical hardware interrupts) can still preempt the SoftDevice ISR.

    Time sensitivity: If your handler takes too long to execute, you risk causing issues, such as missed BLE events or potential overrun situations. Hence, it's crucial to keep these callbacks short and efficient, deferring longer operations to a different context (like a FreeRTOS task).

    *) Can I use semaphores inside those callbacks so that I can hold off calls that are happening too often?

    FreeRTOS FromISR Functions: When interacting with FreeRTOS from an ISR, you need to use the special "FromISR" versions of functions. For example:

    • xSemaphoreGiveFromISR() instead of xSemaphoreGive()
    • xQueueSendFromISR() instead of xQueueSend()

    Deferring Work to Tasks: A common pattern is to defer longer operations to a FreeRTOS task by using a semaphore or queue to signal the task from the ISR. This approach allows the ISR (callback) to quickly return, avoiding potential problems with reentrancy and keeping the SoftDevice responsive.

    *) Can these callbacks in fact be overlapped or does the SD itself wait till it all comes back to it before sending another one?

    The SoftDevice itself can queue multiple events escpecially when the events are triggered from the higher priority contexts within the softdevice, but does not call your event handler if a previous event is still being processed. In other words, the SoftDevice does not "re-enter" the same event callback. This means you don't have to worry about reentrancy within the same event type.

    However, you can still run into issues if multiple different ISRs (or callbacks) try to access shared resources. For example, if you have a high-priority ISR that modifies data that another ISR (from the SoftDevice) also accesses, you need to ensure proper synchronization (e.g., with mutexes or critical sections).

Reply
  • *) These are eventually being called by the soft device but I don't know in what context...   Are these essentially ISR level calls being made from the SD so that they are preemptive (i,.e. if I'm in the callbacks too long I'm going to get overrun by another)?

    Yes, the callbacks triggered by the SoftDevice (e.g., ble_evt_handler) are indeed called from the SoftDevice's Interrupt Service Routine (ISR) context. The SoftDevice runs at a high interrupt priority level, so when it triggers an event (like BLE_GAP_EVT_ADV_REPORT), it is effectively running in an ISR. This means:

    Preemption is enabled: The SoftDevice can interrupt lower-priority tasks, but other ISRs with a higher priority than the SoftDevice ISR (like other critical hardware interrupts) can still preempt the SoftDevice ISR.

    Time sensitivity: If your handler takes too long to execute, you risk causing issues, such as missed BLE events or potential overrun situations. Hence, it's crucial to keep these callbacks short and efficient, deferring longer operations to a different context (like a FreeRTOS task).

    *) Can I use semaphores inside those callbacks so that I can hold off calls that are happening too often?

    FreeRTOS FromISR Functions: When interacting with FreeRTOS from an ISR, you need to use the special "FromISR" versions of functions. For example:

    • xSemaphoreGiveFromISR() instead of xSemaphoreGive()
    • xQueueSendFromISR() instead of xQueueSend()

    Deferring Work to Tasks: A common pattern is to defer longer operations to a FreeRTOS task by using a semaphore or queue to signal the task from the ISR. This approach allows the ISR (callback) to quickly return, avoiding potential problems with reentrancy and keeping the SoftDevice responsive.

    *) Can these callbacks in fact be overlapped or does the SD itself wait till it all comes back to it before sending another one?

    The SoftDevice itself can queue multiple events escpecially when the events are triggered from the higher priority contexts within the softdevice, but does not call your event handler if a previous event is still being processed. In other words, the SoftDevice does not "re-enter" the same event callback. This means you don't have to worry about reentrancy within the same event type.

    However, you can still run into issues if multiple different ISRs (or callbacks) try to access shared resources. For example, if you have a high-priority ISR that modifies data that another ISR (from the SoftDevice) also accesses, you need to ensure proper synchronization (e.g., with mutexes or critical sections).

Children
Related