ARM CM3 PortSuppressTicksAndSleep called with very large argument

superpotion wrote on Friday, May 03, 2019:

I’m trying to implement tickless low power mode on a CM3 MCU, freeRTOS 9. Config as follows

#define configCPU_CLOCK_HZ			108000000
#define configTICK_RATE_HZ			( ( TickType_t ) 1000 )
#define configUSE_TICKLESS_IDLE		1

Everything works perfectly, but a few minutes after booting, when the system is mostly idle, then my vPortSuppressTicksAndSleep is called with a very large xExpectedIdleTime of 648326 ticks (or ms).

This is very strange, as there is is a task ‘vBusHeartbeatTask’ that sends a bus message once per minute, and so would expect a maximum xExpectedIdleTime of only 60000 ticks


rtel wrote on Friday, May 03, 2019:

Hmm, that is going to be a tricky one to debug remotely. To start with
I would have two suggestions - first would be to use the latest version
of FreeRTOS, it should be a drop in replaced. Next would be to set a
break point when the large value i seen so we can try and see where it
comes from. That would involve some pretty deep diving into the data
structures within the kernel.

superpotion wrote on Tuesday, May 07, 2019:

I updated to v10.2, which made no difference. I then had to create a simulated sleep (basically a NOP loop) because the MCU sleep mode breaks the debugger. Finally, I found the issue. I was using the RTC second alarm as a wake up source. The wake-up resolution is 1-sec, but the RTC input clock comes from a pre-scaler, which is fed at 32768Hz. This means the second counter could tick over any time between 1/32768 and 1 sec. It seems that my sloppy arithmetic…


…was the problem, as it was unlikely that 1000ms had actually passed since the alarm was set. Cosnsequently, vTaskStepTick incremented the tick to a value that was too large, such that the waiting task was deemed to have run, and it would be a very long time before the tick counter came around again. The subsequent call to vPortSuppressTicksAndSleep then reflected this with an abnormally large xExpectedIdleTime. To test the theory I simply increased the expected idle time config…


…and shortened the step correction…


…which immediately solved the problem. Next step is to use the MCU’s timers to get a more accurate step correction.

rtel wrote on Tuesday, May 07, 2019:

Thanks for taking the time to report back.