cancel
Showing results for 
Search instead for 
Did you mean: 

EXTI only exits STOP Mode 2 the first time

EC.3
Associate III

Hello,

I have a test app that starts in wake for 5s (with "high" current and GPIO output high) then enters STOP Mode 2 (with "low" current and GPIO output low). It remains in that mode until the EXTI 1 interrupt is triggered by a button press, which wakes it up (current and output go high). That much works.

5s after waking up from the button press it then reenters STOP Mode 2. Pressing the button again does nothing. After seeing that, I added the code below to reinitialize the GPIO both in the EXTI callback function and just before calling HAL_PWREx_EnterSTOP2Mode() - neither one of those made it work. Note that the EXTI callback function calls SystemClock_Config() and HAL_ResumeTick() before the code below is called. Using the debugger, I can see that EXTI1_IRQHandler() does not get called after reentering STOP Mode 2.

What else could be missing? (If I press the button multiple times after the first press but before it reenters STOP I do see the IRQ trigger each time - it's only after it reenters STOP that it will no longer trigger.)

Thanks

__HAL_RCC_GPIOA_CLK_ENABLE();

GPIO_InitTypeDef GPIO_InitStruct = {0};

GPIO_InitStruct.Pin = GPIO_PIN_1;

GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;

GPIO_InitStruct.Pull = GPIO_PULLUP;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

EXTI->IMR1 |= GPIO_PIN_1;

HAL_NVIC_SetPriority(EXTI1_IRQn, 15, 0);

HAL_NVIC_EnableIRQ(EXTI1_IRQn);

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
EC.3
Associate III

I managed to get this to work when using PWR_STOPENTRY_WFE instead of PWR_STOPENTRY_WFI. Since I made a few other changes along with it, I could've just had something wrong with my code. I will note that this implementation also calls SystemClock_Config() and HAL_ResumeTick() in the same function where it enters STOP, just as you suggested, although I had made that change earlier with WFI to no avail.

I did this after looking at https://m0agx.eu/stm32-stop-mode-exti-wakeup-without-hal.html . What it mentions seems to make sense in my current case too:

"The application also uses [GPIO input X] as a regular interrupt source (the interrupt has to be of course enabled separately in the NVIC). In active mode this is not a concern. However, when exiting the stop mode via interrupt, the ISR could run using the wrong clock settings, hence the __disable_irq() and __enable_irq() to first exit the stop mode, reinitialize the clocks and only then service the interrupt."

So I'll most likely stick with the WFE approach.

View solution in original post

3 REPLIES 3
Gautham19
Associate II

@EC.3 

Try to call the SystemClock_Config() and HAL_ResumeTick() in the function in which you are entering the Stop 2 mode not in the EXTI callback. I

Thanks @Gautham19 . I gave that a try but the behavior is the same. My first experiment with STOP2 used a wakeup timer I modeled after https://controllerstech.com/low-power-modes-in-stm32/ , where I successfully used my resume_from_sleep() function in the context of the HAL_RTCEx_WakeUpTimerEventCallback() function. Is it not a good idea to call SystemClock_Config() and HAL_ResumeTick() in an interrupt context?

EC.3
Associate III

I managed to get this to work when using PWR_STOPENTRY_WFE instead of PWR_STOPENTRY_WFI. Since I made a few other changes along with it, I could've just had something wrong with my code. I will note that this implementation also calls SystemClock_Config() and HAL_ResumeTick() in the same function where it enters STOP, just as you suggested, although I had made that change earlier with WFI to no avail.

I did this after looking at https://m0agx.eu/stm32-stop-mode-exti-wakeup-without-hal.html . What it mentions seems to make sense in my current case too:

"The application also uses [GPIO input X] as a regular interrupt source (the interrupt has to be of course enabled separately in the NVIC). In active mode this is not a concern. However, when exiting the stop mode via interrupt, the ISR could run using the wrong clock settings, hence the __disable_irq() and __enable_irq() to first exit the stop mode, reinitialize the clocks and only then service the interrupt."

So I'll most likely stick with the WFE approach.