2016-10-20 11:04 AM
I'd like to implement vPortSuppressTicksAndSleep() to put the MCU into sleep or stop mode when there is nothing to do in FreeRTOS tasks. It should be woken up by an EXTI interrupt or RTC wakeup. In my implementation the RTC is configured to generate wakeup interrupt every 1 ms. By counting interrupts the function knows if given period of time has elapsed. At least in theory. In practice it seems that the variable xActualIdleTime is always zero. The funny thing is that when I put breakpoints and the code is executed line by line, the variable is incremented.
void
vPortSuppressTicksAndSleep(portTickType xExpectedIdleTime)
{
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
// systick IRQ off
PWR_ClearFlag(PWR_FLAG_WU);
watchdog_reset();
volatile
portTickType xActualIdleTime = 0;
eSleepModeStatus eSleepStatus = eTaskConfirmSleepModeStatus();
__asm
volatile
(
''cpsid i''
);
if
(eSleepStatus != eAbortSleep)
{
RTC_WakeUpCmd(ENABLE);
bool
_other_INT_Executed =
false
;
while
((((xActualIdleTime + RTC_ClockRateInMs) / portTICK_RATE_MS) < xExpectedIdleTime) && !_other_INT_Executed)
{
__DSB();
__ISB();
PWR_EnterSleepMode(PWR_Regulator_LowPower, PWR_SLEEPEntry_WFI);
if
(RTC_GetFlagStatus(RTC_FLAG_WUTF)) {
RTC_ClearFlag(RTC_FLAG_WUTF);
xActualIdleTime++;
}
else
{
_other_INT_Executed = 1;
}
}
RTC_WakeUpCmd(DISABLE);
}
if
(xActualIdleTime) vTaskStepTick(xActualIdleTime / portTICK_RATE_MS);
__asm
volatile
(
''cpsie i''
);
_sys_restore_after_lpm();
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
// systick IRQ on
}
What can cause such behavior? Maybe my approach is wrong, but I couldn't find good example for RTC tickless idle.
What should happen with interrupts inside
vPortSuppressTicksAndSleep()
? What is the role of cpsid? Interrupts are necessary to wake up the MCU, but IRQ handlers shouldn't be called? #rtc #freertos #stm32l1 #tick2021-03-16 10:34 AM
@Jeff Tenney
You inspired me a lot. Thanks.