2024-02-15 01:53 AM
I have problems in getting this working. I moved from FreeRTOS to Azure RTOS, and I found out that in general there's lot less information on this RTOS. So I've been looking into the few resources, but I'm afraid I'm missing some important points. Articles in knowledge base show how to manage low power mode in ThreadX, but don't cover tickless mode (while an article about tickless mode is available for FreeRTOS). Examples in CubeMX repository are very simple. I also don't have much experience on STM32U5, and this doesn't help... I'm using CubeMX and HAL functions, IDE is STM32CubeIDE (current versions). Here's the problem:
I'm using ThreadX kernel running at 1 kHz, low power and tickless mode enabled. Two timers, one every 10 ms and another every 250 ms. RTC is interrupting every second, DMA2D interrupt also firing when LCD is updated. TDC is used for the LCD. Threads are waiting on events to perform some actions.Here are partial definitions of the functions related to low power management.
void App_ThreadX_LowPower_Timer_Setup(ULONG count)
{
/* USER CODE BEGIN App_ThreadX_LowPower_Timer_Setup */
// Setup LPTIM4 to wakeup after (ticks * 1000) / TX_TIMER_TICKS_PER_SECOND ms
HAL_LPTIM_DeInit(&hlptim4);
hlptim4.Init.Period = LPTIM_MS_TO_TICK((count * 1000) / TX_TIMER_TICKS_PER_SECOND) - 1;
HAL_LPTIM_Init(&hlptim4);
/* USER CODE END App_ThreadX_LowPower_Timer_Setup */
}
void App_ThreadX_LowPower_Enter(void)
{
/* USER CODE BEGIN App_ThreadX_LowPower_Enter */
HAL_SuspendTick();
// LPTIM4 used to wake up after the designated time
HAL_LPTIM_SetOnce_Start_IT(&hlptim4, LPTIM_CHANNEL_1);
// Enter sleep mode
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
// *** DOESN'T GO TO SLEEP MODE!!! ***
/* USER CODE END App_ThreadX_LowPower_Enter */
}
void App_ThreadX_LowPower_Exit(void)
{
/* USER CODE BEGIN App_ThreadX_LowPower_Exit */
HAL_ResumeTick();
/* USER CODE END App_ThreadX_LowPower_Exit */
}
ULONG App_ThreadX_LowPower_Timer_Adjust(void)
{
/* USER CODE BEGIN App_ThreadX_LowPower_Timer_Adjust */
ULONG actual_ticks_slept;
ULONG elapsed_time_in_ms;
// Determine how long the processor actually slept
// Read counter and stop LPTIM
actual_ticks_slept = HAL_LPTIM_ReadCounter(&hlptim4);
// *** ALWAYS RETURNS 0 or 1 ***
HAL_LPTIM_SetOnce_Stop_IT(&hlptim4, LPTIM_CHANNEL_1);
elapsed_time_in_ms = LPTIM_TICK_TO_MS(actual_ticks_slept);
/* Convert elapsed time to ThreadX ticks. */
actual_ticks_slept = elapsed_time_in_ms / (1000 / TX_TIMER_TICKS_PER_SECOND);
return(actual_ticks_slept);
/* USER CODE END App_ThreadX_LowPower_Timer_Adjust */
}
void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim) {
// NEVER FIRES
if (hlptim->Instance == LPTIM4) {
HAL_LPTIM_SetOnce_Stop_IT(hlptim, LPTIM_CHANNEL_1);
}
}
Of course I expect that RTC and DMA2D interrupts may interfere with the Sleep mode (they're happening at a slower rate compared to the kernel), but what happens is that the MCU never goes to sleep, even when i disable all the interrupts or if the LCD is not updated.
I noticed that ThreadX sets up the low power timer correctly to sleep few milliseconds, but it just doesn't happens.
My questions:
Any suggestion will be helpful, thank you.
2024-02-21 07:41 AM
Hi @paolog
I think it is the SYSTICK interrupt that is waking up the system, the HAL_SuspendTick() is disabling the timebase TIMER interrupt not the SYSTICK.
PS: the SYSTICK is exclusively reserved for ThreadX.
regards
Haithem.
2024-02-26 02:44 AM
Hi @Haithem Rahmani ,thank you for your reply.
Ok, that clarifies, I definitely got confused between the HAL tick and the SYSTICK. Does this mean that having a 1 ms timebase (1 tick = 1 ms) for the RTOS would make the function App_ThreadX_LowPower_Timer_Setup() unnecessary? The ms timer will never go off as the SYSTICK will wake the RTOS before that (sleeping 1 ms at maximum). Variable actual_ticks_slept would then become 1 at maximum (if no interrupt happen during 1 ms), correct?
2024-02-27 11:45 PM
Hi @paolog
indeed, the TIMER won't work until the SYSTICK interrupt is disabled.
below the HAL_SuspendTick() implementation.
__weak void HAL_SuspendTick(void)
{
/* Disable SysTick Interrupt */
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
}
regards
Haithem.
2024-02-28 12:24 AM
Thank you @Haithem Rahmani .
I will review my code about low power and see when the SYSTICK won't be needed, so the MCU will awaken by the HAL timer instead of SYSTICK (i.e. when it can sleep for more than 1 ms).
2024-03-01 07:41 AM
Hi @Haithem Rahmani .
This feature is giving me hard times. Is there an example of ThreadX low power in tickless mode? Plenty of examples using FreeRTOS, but I couldn't find anything comparable with ThreadX. Low power ThreadX examples don't cover tickless mode, surprising enough, as ST seems to be pushing ThreadX as first choice.
Thank you,
Paolo