I am using freertos in my application, and I am now trying to lower the power consumption by implementing tickless mode.
However, I have some issues regarding the implementation of vPortSuppressTicksAndSleep.
I used the freertos_tickless_twrk21f120m project from SDK_2.0_TWR-K21F120M as a starting point. As it is, the example seems to be working, but when starting to modify it and test other frequencies, it does not behave as expected.
The LPTMR is setup with the default config which means 1khz clock.
However, configLPTMR_RATE_HZ is set to SystemCoreClock, which is 120000000.
When calculating the amount of LPTMR counts for one tick, the following expression is used:
ulLPTimerCountsForOneTick = configSYSTICK_CLOCK_HZ / configLPTMR_RATE_HZ;
As these two are defined to be the same, ulLPTimerCountsForOneTick is one. In the example both configTICK_RATE_HZ and configLPTMR_RATE_HZ is 1000, which means that it is correct that one tick is 1 tick on the LPtimer.
But for the general case, the calculation doesn't make any sense, as the it doesn't include anything about the tick rate.
The correct calculation should be:
ulLPTimerCountsForOneTick = configLPTMR_RATE_HZ / configTICK_RATE_HZ;
Fixing this issue allows me to play with different frequency settings of the LPTimer and RTOStick, and the timing looks correct.
But this is only until the sleep period is interrupted by an external interrupt, which sometimes causes the project to hang. This is due to the
vTaskStepTick( ulCompleteTickPeriods );
which is called with
ulCompleteTickPeriods = LPTMR_GetCurrentTimerCount(TICKLESS_LPTMR_BASE_PTR);
This again assumes that the LPTMR is at the same frequency as the rtos tick.
ulCompleteTickPeriods /= ulLPTimerCountsForOneTick;
after reading out the value scales the value correctly, and avoids getting caught in the configASSERT in vTaskStepTick due to wrong input.
I do not know if there are any more errors in this implementation, so it would be great if someone could have a look at this.