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

Interrupts not waking FreeRTOS up in Tickless mode

Hi

I'm working with FreeRTOS with Tickless (RTC) and I was wondering what one should do in order to avoid the FreeRTOS Idle Task to be waken up every time an Interrupt Service Routine has completed the execution.

In Cortex-M4 the SLEEPONEXIT flag in SCR should help with this feature but I cannot let it work with Nordic. Any hints?

Thanks in Advance.

  • I think __SEV;__WFE;__WFE sequence is a safe and well tested sequence to make the chip go to sleep on the second __WFE. Ofcourse there is a time chance that a new event flag is set after the execution of __SEV and __WFE but that is something we need to live with.

    I am not sure why introducing __SEV;__WFE in the place you suggest improves the possibility of clearing the event flag. There are many instructions from this point to the actual next WFE where there is a great possibility for a new event to enter and raise the event flag.

    In this function can you test the performance by not using sd_app_evt_wait and using __SEV;__WFE;__WFE instead of that.

  • I am not really sure but I see a danger that, if i do as you suggest, an event could be lost.

    The sequence disables the application interrupts (sd_nvic_critical_region_enter), then asks FreeRTOS if there is a task pending, and then sets the RTC up.

    Only after this, the event flag would be cleared. But the interrupts are already disabled, so a possible interrupt could have happened in between and we would clear the related event flag before going to sleep.

    This is the documentation I've found About WFE:

    WFE
    Wait For Event.
    Syntax
    WFE{cond}
    where:
    cond Is an optional condition code, see Conditional execution on page 3-18.
    Operation
    WFE is a hint instruction.
    If the event register is 0, WFE suspends execution until one of the following events occurs:
    • an exception, unless masked by the exception mask registers or the current priority level
    • an exception enters the Pending state, if SEVONPEND in the System Control Register is set
    • a Debug Entry request, if Debug is enabled
    • an event signaled by a peripheral or another processor in a multiprocessor system using 
    the SEV instruction.
    If the event register is 1, WFE clears it to 0 and returns immediately.

  • I would recommend you to read this thread.

    dfer said:
    so a possible interrupt could have happened in between and we would clear the related event flag before going to sleep.

     The FreeRTOS port of Nordic enables SEVONPEND, so If the interrupt happens between the SEV and WFE, then you are right that the event is cleared, but the pend bit is set after one more clock cycle, so that should be ok as far as i can see.

  • No I didn't mean that. I meant between sd_nvic_critical_region_enter and __SEV()

    In my opinion this Interrupt would be "lost". Yes, the pending bit would stay set, but the Idle Task wouldn't be woken up after the second __WFE because the Event flag is cleared.

    I don't think that the Event flag would be set again if the Interrupt is still pending, I think it is a one shot Operation (set Interrupt pending -> set Event flag, but only once).

  • You are right, that seems risky. But I think I am deviating a bit from the original discussion.

    Your original suggestion to have __SEV; __WFE before just entering the critical_section is unnecessary since an event/interrupt can happen just after that.

    Do you have any benchmark results that can show that the current sleep implementation makes it execute twice before actually going to sleep?

    If that is really happening, this discussion would be very serious. Initial tests i did does not show what you wrote. But i have not tested extensively. 

Related