cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L476 (nucleo) - FreeRTOS tickless (using LPTIM1)

angeletti
Associate II
Posted on November 12, 2015 at 20:13

Hi guys,

I'm trying to use FreeRTOS in tickless mode using LPTIM1 as tick generator (1ms). I followed the guide on the FreeRTOS webpage but still no luck until now, I mean, the MCU seems to enter the low-power state but vTaskDelay generates uncorrect timing. I attach the code that I'm currently using, hoping someone can help figuring this out.

/* Define the function that is called by portSUPPRESS_TICKS_AND_SLEEP(). */
void
vApplicationSleep( TickType_t xExpectedIdleTime )
{
unsigned 
long
ulLowPowerTimeBeforeSleep, ulLowPowerTimeAfterSleep;
eSleepModeStatus eSleepStatus;
/* Read the current time from a time source that will remain operational
while the microcontroller is in a low power state. */
ulLowPowerTimeBeforeSleep = (uint16_t) HAL_LPTIM_ReadCounter(&LptimHandle);
/* Stop the timer that is generating the tick interrupt. */
HAL_NVIC_DisableIRQ(LPTIM1_IRQn);
/* Enter a critical section that will not effect interrupts bringing the MCU
out of sleep mode. */
__disable_irq();
/* Ensure it is still ok to enter the sleep mode. */
eSleepStatus = eTaskConfirmSleepModeStatus();
if
( eSleepStatus == eAbortSleep )
{
/* A task has been moved out of the Blocked state since this macro was
executed, or a context siwth is being held pending. Do not enter a
sleep state. Restart the tick and exit the critical section. */
__enable_irq();
HAL_NVIC_EnableIRQ(LPTIM1_IRQn);
HAL_LPTIM_Counter_Start_IT(&LptimHandle, configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ);
}
else
{
if
( eSleepStatus == eNoTasksWaitingTimeout )
{
/* It is not necessary to configure an interrupt to bring the
microcontroller out of its low power state at a fixed time in the
future. */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
}
else
{
/* Configure an interrupt to bring the microcontroller out of its low
power state at the time the kernel next needs to execute. The
interrupt must be generated from a source that remains operational
when the microcontroller is in a low power state. */
HAL_LPTIM_Counter_Start_IT(&LptimHandle, (configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ) * xExpectedIdleTime);
HAL_NVIC_EnableIRQ(LPTIM1_IRQn);
/* Enter the low power state. */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
/* Determine how long the microcontroller was actually in a low power
state for, which will be less than xExpectedIdleTime if the
microcontroller was brought out of low power mode by an interrupt
other than that configured by the vSetWakeTimeInterrupt() call.
Note that the scheduler is suspended before
portSUPPRESS_TICKS_AND_SLEEP() is called, and resumed when
portSUPPRESS_TICKS_AND_SLEEP() returns. Therefore no other tasks will
execute until this function completes. */
ulLowPowerTimeAfterSleep = (uint16_t) HAL_LPTIM_ReadCounter(&LptimHandle);
/* Correct the kernels tick count to account for the time the
microcontroller spent in its low power state. */
if
( ulLowPowerTimeBeforeSleep > ulLowPowerTimeAfterSleep)
vTaskStepTick( (ulLowPowerTimeBeforeSleep - ulLowPowerTimeAfterSleep) / 32 );
else
vTaskStepTick( (ulLowPowerTimeAfterSleep - ulLowPowerTimeBeforeSleep) /32);
}
/* Exit the critical section - it might be possible to do this immediately
after the prvSleep() calls. */
__enable_irq();
/* Restart the timer that is generating the tick interrupt. */
HAL_NVIC_EnableIRQ(LPTIM1_IRQn);
}
}

#nucleo #stm32l476 #freertos
0 REPLIES 0