cancel
Showing results for 
Search instead for 
Did you mean: 

How to ensure interrupt handling before going to sleep/stop mode

JBond.1
Senior

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;
	}
}

 

 

 

8 REPLIES 8
Sarra.S
ST Employee

Hello @JBond.1

You can check for pending interrupts before entering stop/sleep mode, check for pending bits, something like this: 

 if (__HAL_GPIO_EXTI_GET_IT(CALL_Pin) == RESET)
        {
            HAL_SuspendTick();
            HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
            HAL_ResumeTick();
        }

        while (HAL_GetTick() < GoToSleepAfterTick)
        {
             //...
        }

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

But will it handle all cases?

        if (__HAL_GPIO_EXTI_GET_IT(CALL_Pin) == RESET)
        {
            // interupt could occure here???
            HAL_SuspendTick();
            // interupt could occure here???
            HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
            HAL_ResumeTick();
        }

        while (HAL_GetTick() < GoToSleepAfterTick)
        {
             //...
        }


Also will interrupts even be "pending"? I think interrupts have higher priority than main loop?

I guess I could check if `GoToSleepAfterTick` have not been changed just before sleep. But interrupt could still occur just after check?

    while (1)
    {
        HAL_SuspendTick();

        if (HAL_GetTick() >= GoToSleepAfterTick)
        {
             // interupt could occure here???
             HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
        }

        HAL_ResumeTick();

        while (HAL_GetTick() < GoToSleepAfterTick)
        {
             //...
        }
    }





gbm
Principal

Basically, the problem you describe does not exist at all.

If you consider standard sleep mode, all the peripheral blocks are active, so any enabled interrupt will wake up the MCU from sleep. If think of a deeper sleep, then when you put the MCU to sleep you agree to ignore most of events which are handled in normal operation state, so it makes no difference if the event is handled or not. No difference if the event occurred one microsecond before sleep or after it - it must be safe to ignore it.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
MM..1
Chief III

Primary your use haltick have mistake.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == CALL_Pin)
	{
		GoToSleepAfterTick = HAL_GetTick() + STAY_WAKE_FOR_TICK;
	}
}

example GetTick isnt neverending increment value. On overrun your while fail ...

And better is leave callback empty and place code after wake...

    while (1)
    {
        HAL_SuspendTick();
        if(!ignoresleep)HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI);
        HAL_ResumeTick();
GoToSleepAfterTick= ...
        while (HAL_GetTick() != GoToSleepAfterTick) //right for overrun
        {
             //...
        }
	
        // interupt could occure here??? when yes place in callback bool ignoresleep
    }

It does mater to handle all interrupt, for example if I am counting button presses for Morse code. If one button press happens just before sleep it wont wake-up because its not yet into sleep mode?


Yes, I see the issue with uint32 overload, but I guess that's another story... It still can work for 49days until overload and if its awake only 10secs other time does not count into those 49days.

I cant remove code from callback, because it wont reset timer on each button click callback. I need to reset 10seconds countdown on each button click...

JBond.1
Senior

I guess the solution would be to set "wake up on interrupt only", so it would listen to button press and button press would start/reset(if timer started) timer, but I guess I wont be able to go to "stop" mode if I need timer? Or I can go into "stop" mode after timer end in timer interrupt?

Basically on each button interrupt it should start/reset 10seconds timer and after 10seconds timer end (10seconds of button inactive) it should stop timer and go to "stop" mode and wait for button activity.

In normal code button do somethink and time update is place into this code, but can be in exti ...

You still ask unreal question, normal situation instruction asm go to sleep cant be interrupted, then ISR occurs before or after... before is your issue because if timeout then is skip. If this is issue in your app then set second wake source for example timer ... But if user is not android machine and pick nano second click = system no react simply repeat click wake.