2013-01-30 06:17 AM
Hi,
we have a problem with the STOP mode of the STM32F3. We have the feeling, that the F3 immediately returns from STOP mode, if ANY interrupt is enabled and has been activated before entering the STOP mode. The second entry into STOP mode is working (does not return without an event). We have a little demo for the STM32F3DISCOVERY board, that demonstrates this behaviour (the main.c is attached). To provoke the error, do the following: 1. disable (''comment-out'') the second WFE in line 58 2. Build and run the project 3. Press and release the button. Nothing to be seen, but in fact the LED is switched on and off very fast (can be seen with an osci; the same signal is on PA3 for verfication). With the following change the error could be ''worked around'' (at least in my tests): 1. Enable the 2nd WFE and all following NOPs 2. Build and run the project 3. Press and Release the button. After releasing the button the blue LED is switched on, the MCU is in STOP mode now. 4. Press and release the button. The MCU wakes up, the LED is switched off. Another problem occurs, if you remove the 4 NOPs after the 2nd WFE. Then the core goes into hardfault handler. With an STM32F1 and L1 we don't have these problems! Can anyone else confirm this behaviour and/or has an explanation for it? Any general comments and hints related to the STOP mode especially with the STM32F3xx are appreciated. Has anyone the STOP mode of the STM32F3 working?? thanks in advance, Ren� #stm32f3-stop-mode-problem-wfe2013-02-15 03:17 AM
Hi René,
Try this sequence of code and let me know if you still face the same issue:/* init the TIM7 */
RCC->APB1ENR |= RCC_APB1ENR_TIM7EN; TIM7->PSC = 7; // => 1 MHz timer clock frequency (at PCLK=8 MHz) TIM7->ARR = 1000 - 1; // => 1 kHz interrupt rate TIM7->DIER = TIM_DIER_UIE; // enable the update interrupt NVIC_EnableIRQ( TIM7_IRQn ); TIM7->CR1 |= TIM_CR1_CEN; // start the timer RCC->APB1ENR |= RCC_APB1Periph_PWR;/* Configure PA0 pin as input floating */
RCC->AHBENR |= RCC_AHBPeriph_GPIOA; RCC->APB2ENR |= RCC_APB2Periph_SYSCFG; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_Init(GPIOA, &GPIO_InitStructure);EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); PWR_WakeUpPinCmd(PWR_WakeUpPin_1, ENABLE); /* Configure the pin to be toggled: PB2 */ RCC->AHBENR |= RCC_AHBPeriph_GPIOB; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); /* Configure PWR registers to enter STOP mode */ PWR->CR &= 0xFFFFFFFC; // clear the PDDS and LPDS bits PWR->CR |= 0x00000000; // STOP Mode: Regulator on // PWR->CR |= 0x00000001; // STOP Mode: Regulator off/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; __WFE();/* after waking-up from STOP mode this is the first instruction to be executed */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); /* Configure PB1 as Output */GPIOB->ODR = 0x00000002;
If you think that the interrupt is the problem root cause, try to disable it just before entering stop mode (not only clear the pending interrupts). I have a doubt if the MCU really enter stop mode with examples you provided -to re-check-. Regards, ST.MCUTo give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2013-02-15 04:54 AM
Hi st.mcu,
I have tested it. If I add a TIM7 interrupt handler and let the example run as it is, it works as it is expected to. BUT! And that's the important point. It only works as long as there has not been an interrupt BEFORE the WFE is executed. I have added a tick counter to your example and if I wait for it to become > 0, before calling WFE, WFE returns IMMEDIATELY, regardless of disabled IRQ or not. See below your modified example code. I have changed the output port from PB2 to PE8 (I am testing this with an STM32F3DISCOVERY board), I have added the TIM7 ISR and the tick counter and I am waiting for the tick counter to become > 0, before calling WFE. Additionally I have added a __disable_irq() according to your recommendation. If I disable the while(ticks==0) loop, the firmware works and the output port is switched AFTER the PA0 input is toggled. If you wait for ticks to become != 0, the example does NOT work. WFE returns immediately and the output port is switched on IMMEDIATLY after reset. To make sure, the debugger doesn't make trouble, I have disconnected the probe, powered off the target and tested it without debug probe. Same effect. WFE returns immediately. Could you please test the code with the modifications I made (except the one related to the output port)? Are you getting the same behaviour? #include <stdint.h> #include <stm32f37x.h> volatile uint32_t ticks = 0; void TIM7_IRQHandler(void); void TIM7_IRQHandler(void) { TIM_ClearITPendingBit( TIM7, TIM_IT_Update ); ticks++; } int main(void) { int v = 0; GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; /* init the TIM7 */ RCC->APB1ENR |= RCC_APB1ENR_TIM7EN; TIM7->PSC = 7; // => 1 MHz timer clock frequency (at PCLK=8 MHz) TIM7->ARR = 1000 - 1; // => 1 kHz interrupt rate TIM7->DIER = TIM_DIER_UIE; // enable the update interrupt NVIC_EnableIRQ( TIM7_IRQn ); TIM7->CR1 |= TIM_CR1_CEN; // start the timer RCC->APB1ENR |= RCC_APB1Periph_PWR; /* Configure PA0 pin as input floating */ RCC->AHBENR |= RCC_AHBPeriph_GPIOA; RCC->APB2ENR |= RCC_APB2Periph_SYSCFG; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_Init(GPIOA, &GPIO_InitStructure); EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); PWR_WakeUpPinCmd(PWR_WakeUpPin_1, ENABLE); /* Configure the pin to be toggled: PE2 */ RCC->AHBENR |= RCC_AHBPeriph_GPIOE; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_Init(GPIOE, &GPIO_InitStructure); /* Configure PWR registers to enter STOP mode */ PWR->CR &= 0xFFFFFFFC; // clear the PDDS and LPDS bits PWR->CR |= 0x00000000; // STOP Mode: Regulator on // PWR->CR |= 0x00000001; // STOP Mode: Regulator off while( ticks == 0 ) { v++; v++; } __disable_irq(); /* Set SLEEPDEEP bit of Cortex System Control Register */ SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; __WFE(); /* after waking-up from STOP mode this is the first instruction to be executed */ SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); /* Configure PE8 as Output */ GPIOE->ODR = 0x00000100; return( 0 ); } //$(ProjectDir)/STM32F37x_StdPeriph_Driver/incint main(void) To be more clearly, my assumption is as follows: If there has ever been an interrupt before trying to put the STM32F3 into STOP mode using WFE, WFE returns immediately. So I guess, that the internal 1 bit event register is set, although no interrupt source is configured to generate an event. That's why WFE returns immediately.2013-02-21 09:00 AM
Hi René,
Sorry for this delayed reply. I tested the code you provided and got the same result: it works only if there are 2 WFE commands. Checking the power consumption values, it seems that the mcu doesn't enter stop mode if only one WFE command is executed. Seeing the following explanation for WFE command from ARM, I suspect that the event register is 1. But I don't have an explanation why. This is the ARM explanation:WFE
is a hint instruction.
If the event register is 0,
WFE
suspends execution until one of the following events occurs:
- an exception, unless masked by the exception mask registers or the current priority level
- an exception enters the Pending state, if
SEVONPEND
in the System Control Register is set
- a Debug Entry request, if Debug is enabled
- an event signaled by a peripheral or another processor in a multiprocessor system using the
SEV
instruction.
If the event register is 1,
WFE
clears it to 0 and returns immediately. That is why the second WFE works fine.
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.
2013-02-21 10:49 AM
Hi,
thank you for (at least) the confirmation of what I have seen! My guess is, that there is a bug (or a ''device limitation'' to speak in terms of the ST documentation) in the STM32F3. The event register shouldn't be set. It should only be set, if an interrupt becomes pending, THAT IS CONFIGURED to set the event register, for example one of the EXTI pins. But in the F3 it seems, that EVERY interrupt sets the event register. At least I have seen this for the SysTick timer and for other timers (as in the example you provided). With the STM32L1 and the STM32F1 I haven't seen this behaviour. If this actually is a bug, it would be fine, if there was an entry in the errata sheet about that. My workaround for now is, to make sure, that at least one interrupt becomes pending before I call WFE (I am using the systick counter for that). Then I call WFE twice. The first one returns immediately and the second one puts the chip in STOP mode. In the tests I have made so far, that seems to work. But if there is actually a bug in the chip, what do I have to be aware of else...2015-10-06 11:09 AM
Looks like I'm having almost the same problem 2 years later with STM32F4 and STM32F7. I use WFI and it also immediately wakes up from STOP. I found turning
off SysTick before entering STOP allows it to stay in STOP mode until the real time clock alarm interrupt wakes it up:while (true){ HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, 0x2000, RTC_WAKEUPCLOCK_RTCCLK_DIV16); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle); SYSCLKConfig_STOP(); // restore PLL as system clock HAL_Delay(1000);}Maybe this will also allow WFE not experience spurious wakeups. I don't have a multicore processor, so I can't test. Why isn't turning off SysTick in the STM32F4/7 Cube HAL?2015-10-06 11:37 AM
SysTick is a system handler, but acts like an interrupt.
WFI = Wait For Interrupt Not surprising that when waiting for an interrupt, any will do, it's hardly spurious or unexpected. The OP isn't using HALWhy isn't turning off SysTick in the STM32F4/7 Cube HAL? Huh? Not sure what that means exactly, but the HAL enables the SysTick so that HAL_Delay() and other assorted timeouts function.2015-10-08 02:35 AM
I meant that ST should disable and re-enable SysTick inside HAL_PWR_EnterSTOPMode().