I’m new to using FreeRTOS and have been working on adding tickless idle mode on a project running on a Cortex M0 based PSoC to allow the use of deep sleep modes when systick is not running.
I think I have things mostly working, but have noticed an issue upon wakeup from deep sleep where it appears none of my tasks are serviced until 1 full tick AFTER I am awake and ready to start processing again. I am calling vTaskStepTick() with the appropriate number of ticks and the RTOS seems to be keeping track of time correctly, I just want to get rid of this wasted idle tick when I wake up.
Here is a screenshot of my signals: http://i.imgur.com/OK09p4w.png
I have a simple LED task and CapSense (touch sensing) task running on a 10 ms interval. The Deep Sleep channel is showing when the part is going into tickless idle mode and the CPU Sleep channel is when I’m only sleeping the CPU (which only occurs when the system is idling for less than the configEXPECTED_IDLE_TIME_BEFORE_SLEEP = 2 parameter).
As can be seen, when the Deep Sleep signal deasserts the system wakes up but the system appears to idle for 1 full tick (CPU Sleep) before my LED Task and CapSense task get to run. I’d like them to run immediately to increase my deep sleep time.
Any ideas why this is? Note the SysTick source is OFF during the tickless/DeepSleep mode, so there is no pending SysTick interrupt when I come out of deepsleep and finish vApplicationSleep. Was wondering if the RTOS is expecting this to be the case or if I should try to force a pending interrupt when coming out of deepsleep. Or is there something else going on here?
Some of the behaviour when going into and out of tickless idle is quite subtle with regards to calculating partial tick periods on the way in, and on the way out. As this is your own implementation (I’m not aware that we provide a tickless implementation on an M0 although maybe the M3/4 version would work) I can’t really suggest why you may be seeing the issue. If you are also placing the CPU into non-deep sleep (presumably in the idle task, but you didn’t say) then that is running when you come out of deep sleep and going into a low sleep. You also don’t say what brings you out of deep sleep as you imply the timer is off - if the interrupt that is bringing you out of deep sleep is not also forcing a contact switch then that could be another reason.
Thanks for the reply, I am using a watchdog timer based on an internal low-speed oscillator as my wakeup source from deepsleep/tickless idle. The CPU sleep (non deep-sleep) is done in the idle task.
Is there a set API I should use after waking from deep sleep to inform the OS that I am done idling and force a context switch? I assumed the OS would check to see if it is done idling when I return from my implementation of vApplicationSleep(), but it appears this doesn’t happen for 1 systick after I return.
Normally the interrupt that causes the system to leave low power mode
will attempt a context switch. However, the scheduler is suspended
while the tick is off, so the context switch remains pending. When the
tick is turned back on the scheduler is unsuspended, and the act of
un-suspending the scheduler will cause the pending context switch to
execute.