ARM CM3 PortSuppressTicksAndSleep called with very large argument

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

define configCPUCLOCKHZ 108000000

define configTICKRATEHZ ( ( TickType_t ) 1000 )

define configUSETICKLESSIDLE 1

define configEXPECTEDIDLETIMEBEFORESLEEP 1000

~~~ 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 ~~~ for(;;) { multiDropBusNotify(); vTaskDelay(60000); } ~~~

ARM CM3 PortSuppressTicksAndSleep called with very large argument

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.

ARM CM3 PortSuppressTicksAndSleep called with very large argument

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… ~~~ vTaskStepTick((rtcAfterSleep-rtcBeforeSleep)*1000); ~~~ …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… ~~~

define configEXPECTEDIDLETIMEBEFORESLEEP 2000

~~~ …and shortened the step correction… ~~~ vTaskStepTick((rtcAfterSleep-rtcBeforeSleep-1)*1000); ~~~ …which immediately solved the problem. Next step is to use the MCU’s timers to get a more accurate step correction.

ARM CM3 PortSuppressTicksAndSleep called with very large argument

Thanks for taking the time to report back.