AnsweredAssumed Answered

STM32L1 FreeRTOS tickless idle with RTC wakeup

Question asked by niemirowski.grzegorz on Oct 20, 2016
Latest reply on Oct 23, 2016 by niemirowski.grzegorz
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?

Outcomes