2025-02-08 8:44 AM - edited 2025-02-08 8:57 AM
Hi, I want to go to sleep/stop mode with STM32 and wake on interrupt. After last interrupt it should wait for 10sec and go back to sleep. But I see an edge case where interrupt could occur just before going to sleep/stop mode.
How do I handle interrupt just before going to sleep/stop mode (cancel sleep/stop mode)?
Basically force WAKE from sleep/stop mode even if STM32 is not yet in sleep/stop mode?
#define STAY_WAKE_FOR_TICK 10000
static volatile uint32_t GoToSleepAfterTick;
void main(void)
{
//...
while (1)
{
HAL_SuspendTick();
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
HAL_ResumeTick();
while (HAL_GetTick() < GoToSleepAfterTick)
{
//...
}
// interupt could occure here???
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == CALL_Pin)
{
GoToSleepAfterTick = HAL_GetTick() + STAY_WAKE_FOR_TICK;
}
}
2026-03-13 11:44 PM
Your concern is absolutely valid.
Let's assume the code where we receive events in an interrupt, handle events in main loop and sleep if there are no events.
void myiSR() {
events.Add();
}
void main() {
while (1) {
while (events.Available()) {
HandleAndRemoveEvent(events);
}
if (!events.Available()) {
// do something right before sleep
Sleep();
}
}
}We check for events in line 10 and go to Sleep in line 12, if interrupt happens between lines 10 and 12 it will be handled by myiSR and event will be added to the list BUT it will not prevent Sleep.
You can make this problem more obvious if you make transition from line 10 to 12 longer, put Hal_Delay() in line 11 for example.
To overcome the problem I usually use a one-shot timer to generate delayed interrupt. Timer period must be short enough but definitely longer than a time it takes to get from line 10 to 12.
I start timer in myiSR. If myiSR happens outside lines 10-12 event is handled in a normal way and timer interrupt is just ignored. It myiSR happens between lines 10-12, event is not handled and Sleep is initiated, but timer interrupt wakes MCU from sleep and makes it handle the event.
void myiSR() {
events.Add();
__HAL_TIM_ENABLE(timer_onetime_inst);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim == timer_onetime_inst) {
__HAL_TIM_DISABLE(htim);
}
}
void main() {
while (1) {
while (events.Available()) {
HandleAndRemoveEvent(events);
}
if (!events.Available()) {
// do something right before sleep
Sleep();
}
}
}
2026-03-14 1:04 AM
Absurd. Primary this is year old ticket. And your code is more absurd as @JBond.1
Nobody eco based set code to do nothink 10s at max speed for waiting somethink...
2026-03-14 6:39 AM
> Let's assume the code where we receive events in an interrupt, handle events in main loop and sleep if there are no events.
This is not the same problem. You are introducing a race condition, in which case yes, the code contains a race condition. Don't do that. The interrupt is still handled before sleep.