cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32U031 -- Problems waking from STOP2 with EXTI

sb_st
Associate III

Howdy;

I have a li'l stm32u031, with a pushbutton attached to PA0. This MCU is clocked with no external oscillators. 

I've configured the button/pin to work with Timer2/Channel1 in Input Capture mode when the MCU is in run mode, to detect and measure button presses. This works swell. 

I'd like to be able to put this device into STOP2 mode, and be able to re-awaken it with the button. My understanding is that I'd do this by de-initing it as an alt function pin, and re-initing it for EXTI. 

At the moment, I'm doing this:

    // Stop all timer channels
    HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_1);
    HAL_TIM_OC_Stop_IT(&htim2, TIM_CHANNEL_2);
    HAL_TIM_OC_Stop_IT(&htim2, TIM_CHANNEL_3);

    // Stop the timer itself
    HAL_TIM_Base_Stop(&htim2);

    // Mask any stray interrupts and clear latched flags
    __HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4);
    __HAL_TIM_CLEAR_FLAG(&htim2,  TIM_FLAG_UPDATE | TIM_FLAG_CC1  | TIM_FLAG_CC2  | TIM_FLAG_CC3  | TIM_FLAG_CC4 |
                                  TIM_FLAG_CC1OF | TIM_FLAG_CC2OF | TIM_FLAG_CC3OF | TIM_FLAG_CC4OF);

    // Switch NVIC off + clear any pending interrupts
    // to avoid surprise ISR on resume
    NVIC_DisableIRQ(TIM2_IRQn);
    NVIC_ClearPendingIRQ(TIM2_IRQn);

    // Disconnect the peripheral clock for a few extra µA
    __HAL_RCC_TIM2_CLK_DISABLE();

    // Now we are going to configure our
    // button to create an interrupt when pressed
    // using EXTI instead of our timer.

    // We are going to de-init our pin
    // which disconnect it from Timer2.
    HAL_GPIO_DeInit(MAIN_BUTTON_GPIO_Port, MAIN_BUTTON_Pin);

    // Then re-configure it thusly:
    GPIO_InitTypeDef gpio_config = {0};
    gpio_config.Pin  = MAIN_BUTTON_Pin;
    gpio_config.Mode = GPIO_MODE_IT_RISING;
    gpio_config.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(MAIN_BUTTON_GPIO_Port, &gpio_config);

    // Clear any stale pending before sleeping
    __HAL_GPIO_EXTI_CLEAR_IT(MAIN_BUTTON_Pin);

    NVIC_ClearPendingIRQ(EXTI0_1_IRQn);
    HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);


    // now, sleepytime:
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    RCC->CFGR |= RCC_CFGR_STOPWUCK;
    HAL_SuspendTick();
    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);

This only partially works - I can put it to sleep, then wake it up a time or two using this button. But eventually it seems to get 'stuck' in STOP2, and the button presses no longer work. This behavior is repeatable, but the 'number of wakeups" I seem to be able to perform changes each time I restart the device - sometimes it won't wake up at all, sometimes I get 2-3 wakeups before it stops working. 

I've tried all manner of mucking around using the higher-level HAL stuff, as well as individual LL syntax, but I can't quite seem to fix this problem, nor do I understand why it's happening. This line:

    RCC->CFGR |= RCC_CFGR_STOPWUCK;

I found in this thread, where someone else seemed to be having a similar problem (maybe), but it doesn't seem to affect the experience I'm having. 

I'm curious if anyone might have some advice.

thanks!

 

11 REPLIES 11

Hello @sb_st 

Did you change the GPIO pull configuration of EXTI button to GPIO_PULLUP?

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.
Saket_Om

To be honest, I don't remember - I tried a ton of stuff to make this work, and eventually landed on the issue I highlighted here, which identified my issue as being related to using the RNG peripheral. I think the GPIO switching from timer to EXTI was not actually the root of my problems. 

My work around, also mentioned in that post - clocking RNG from PLLQ rather than MSI - got my system behavior in a more stable manner. Why this is I'm