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.

  • Yes as said it you set a debug port before going to sleep and then reset ti immediately after WFE you'll see that the function is always executed twice.

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

    this isn't right, since I would do the SEV/WFE before  sd_nvic_critical_region_enter and later I would call only WFE (not SEV) thus no interrupts/events would be lost. If an interrupt occurs after sd_nvic_critical_region_enter, it would set the event flag, thus preventing the processor to go to sleep at the next WFE

  • I see your point but 

    dfer said:
    The Event flag is Always set because either a Task has been Yielded or an Interrupt has occured while the processor was not sleeping. The first time __WFE(); is executed will almost always go Forward without sleeping, causing another call to vPortSuppressTicksAndSleep form FreeRTOS.

    I see that the first one (Event set due to task yield) is not a problem, since the scheduler needs to be called before sleeping which is correct behavior that the sleep is aborted. You should not at this point try to clear that event that is the result of any state change of the task, this could cause deadlocks.

    But I see that you have a point that if there is an interrupt  happening inbetween the critical section, then the vPortSuppressTicksAndSleep code unnecessarily exits the sleep routine.

    Wow, this is a good find. I am sorry that i missed to see the details of your previous reply. An interrupt could occur even while in critical section setting the event flag, so I am not sure that just clearing the event before entering critical section helps that much??

  • I feel we are a bit drifting from each other away.

    So to recap:

    any Task switch sets the Event flag with __SEV, see portYIELD macro (why? I guess  SCB->ICSR = SCB_ICSR_PENDSVSET_Msk would be enough, the PendSV interrupt would be set pending and the event flag is set pending, see SEVONPEND) 

    the tick interrupt sets the event flag with __SEV (why? see comment above)

    any Interrupt sets the Event flag automatically (see SEVONPEND)

    So the chances that we come to vPortSuppressTicksAndSleep with the event flag already set are high. This event flag setting has happened most probably in the past and the scheduler has already served the necessary task switches. 

    Now, resetting the event flag before the sd_nvic_critical_region_enter function call should be ok, because the ISR of an interrupt happening just before sd_nvic_critical_region_enter would be anyway invoked. If this ISR(*) triggers a FreeRTOS task, the scheduler would set that task to Ready.

    Now the sd_nvic_critical_region_enter  is called. 

    After this, a masked application interrupt sets the event flag but the ISR is not executed. 

    After sd_nvic_critical_region_enter, the function eTaskConfirmSleepModeStatus is called, which will abort the sleep process if a task or a task switch is pending (see served ISR above(*) ) - so here I see no problems.

    If an interrupt happens after eTaskConfirmSleepModeStatus, it will set the event flag and the next WFE will be skipped - here I see no problem.

    If an interrupt occurs after WFE, the normal wake up prcedure will happen and again here I see no problems.

  • dfer said:
    any Task switch sets the Event flag with __SEV, see portYIELD macro (why? I guess  SCB->ICSR = SCB_ICSR_PENDSVSET_Msk would be enough, the PendSV interrupt would be set pending and the event flag is set pending, see SEVONPEND) 

    You are right. I think SEV is not needed here, but I think it is a harmless addition. SEVONPEND bit set does not need SEV to be added explicitly after pending this to ICSR.

    dfer said:
    So the chances that we come to vPortSuppressTicksAndSleep with the event flag already set are high. This event flag setting has happened most probably in the past and the scheduler has already served the necessary task switches. 

    Agreed...

    dfer said:
    After this, a masked application interrupt sets the event flag but the ISR is not executed. 

    Agreed, because of SEVONPEND. 

     

    dfer said:
    After sd_nvic_critical_region_enter, the function eTaskConfirmSleepModeStatus is called, which will abort the sleep process if a task or a task switch is pending (see served ISR above(*) ) - so here I see no problems.

     Agreed.

     

    dfer said:
    If an interrupt happens after eTaskConfirmSleepModeStatus, it will set the event flag and the next WFE will be skipped - here I see no problem.

     Agreed.

     

    dfer said:
    If an interrupt occurs after WFE, the normal wake up prcedure will happen and again here I see no problems.

     Agreed.

    i agree with you Davide, i missed to see the check eTaskConfirmSleepModeStatus. Should be safe to clear the event just before entering the critical section.

Related