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

FreeRTOS and SoftDevice events: hard fault

We have used FreeRTOS a lot, also on nRF51 and nRF52. Now I'm trying to migrate our nRF52 code form SDK11-alpha and SoftDevice 2.0.0-7-alpha (?) to the most recent versions. Most of things are working but one problem remains. We use s132_nrf52_2.0.1_softdevice.hex.

Everything runs fine for a few minutes, but then some race condition occurs and causes a hard fault. Possibly when a lower priority task is preempted, due to a tasks invoked by calling intern_softdevice_events_execute();

Question 1) Any ideas why in the SoftDevice event handler (ble_new_event_handler() copied straight form the SDK11 example ble_app_hrs_freeertos) fails with a stack trace like this:

HardFault_handler () ... gcc_startup_nrf52.s
<signal_handler called>
0x000092a in ?? ()
<signal_handler called>
... in vPortStartFirstTask()

Otherwise this looks good to me but should have exited the previous signal handler before the new one gets called. This stack trace is (manually) copied probably from a test running the signal handled event task on the lowest FreeRTOS priority.

If using a high FreeRTOS task priority, then the same error happens at portYIELD_FROM_ISR(yield_req) in the ble_new_event_handler(). Specificly the hard fault happens in portmacro_cmsis.h at the end of the portYIELD() call at the __ISB(); line.

Our application logic can manage with omitting the portYIELD_FROM_ISR() call in ble_new_event_handler() and that seems to fix the instability. This is not optimal.

Question 2) Is there somewhere documentation on how the SoftDevice handles mutual exclusivity - in RTOS context? We use several FreeRTOS tasks and priorities, with multiple of them making calls to softdevice functions...

Is there a mutex on the SoftDevice side so that we can just call the functions without putting a mutex sempahore around every SD call (which would become cumbersome with asynchronous calls). And is there something we should avoid when processing events firm SoftDevice and making new softdevice calls based on those?

I'm wondering it some of these issues is causing the trouble above...

Parents
  • Edit: The problem was configLIBRARY_LOWEST_INTERRUPT_PRIORITY. Got it working earlier, but took this long :( to do all the testing and removing my workarounds etc. I did "check" that priority setting already earlier, but due to mixed up #ifdef:s the line with 0x0f was not in use...

    That fixed the all the issues with portYIELD() and ble_new_event_handler()


    I may have found part of the problem. Every couple of minutes there used to be hard faults with stack trace like this.

    image description

    It seems to me that there is a flaw on the FreeRTOS port and it's integration to SoftDevice event handling. It (probably only) appears when ble_new_event_handler causes a FreeRTOS task to yield AND there are multiple events in the soft device queue.

    The ble_new_event_handler (as copied from the SDK examples) enables soft device interrupts when yielding with portYIELD(). But it should not - before all the queued events have been processed in intern_softdevice_events_execute() in softdevice_handler.c

    Wrote a workaround and this error with SWI2_EGU2_IRQHandler has not appeared since. I think there is no way doing this without modifying the intern_softdevice_events_execute() code. Need to do some more experimenting, but I'll open a support ticket on this.

Reply
  • Edit: The problem was configLIBRARY_LOWEST_INTERRUPT_PRIORITY. Got it working earlier, but took this long :( to do all the testing and removing my workarounds etc. I did "check" that priority setting already earlier, but due to mixed up #ifdef:s the line with 0x0f was not in use...

    That fixed the all the issues with portYIELD() and ble_new_event_handler()


    I may have found part of the problem. Every couple of minutes there used to be hard faults with stack trace like this.

    image description

    It seems to me that there is a flaw on the FreeRTOS port and it's integration to SoftDevice event handling. It (probably only) appears when ble_new_event_handler causes a FreeRTOS task to yield AND there are multiple events in the soft device queue.

    The ble_new_event_handler (as copied from the SDK examples) enables soft device interrupts when yielding with portYIELD(). But it should not - before all the queued events have been processed in intern_softdevice_events_execute() in softdevice_handler.c

    Wrote a workaround and this error with SWI2_EGU2_IRQHandler has not appeared since. I think there is no way doing this without modifying the intern_softdevice_events_execute() code. Need to do some more experimenting, but I'll open a support ticket on this.

Children
Related