I am working on a device with a button that is supposed to turn it on (when pressed briefly) and off (when held longer). The MCU is an STM32L432. The button is connected to PB0. I want to use EXTI as the wakeup source from stop mode 2.
I skipped the low power mode stuff for clarity.
In the main loop I am polling the button. If it is held for more than 3 seconds I call this function:
void power_shutdown(void){
volatile uint32_t x = 10000000;
while (x--){ //ugly delay for button bounce, this one is ~2s
while (PIN_BTN_LOW){} //wait for the button to be released
}
//configure button interrupt
SYSCFG->EXTICR[0] = SYSCFG_EXTICR1_EXTI0_PB; //PB0 connected to EXTI0
EXTI->IMR1 = 0x01; //enable EXTI0 interrupt
EXTI->FTSR1 = 0x01; //EXTI0 line falling edge trigger enable
//turn off LEDs
PIN_LED_GREEN_HIGH();
PIN_LED_BLUE_HIGH();
debugf("PR1 %08X", EXTI->PR1); //this is always 0x00000000
debugf("PR2 %08X", EXTI->PR2); //this is always 0x00000000
NVIC_EnableIRQ(EXTI0_IRQn);
PIN_LED_BLUE_LOW();
//dummy loop - entry to low power mode will be here
while (1){}
}
I have the following interrupt handler:
void EXTI0_IRQHandler(void){
PIN_LED_BLUE_HIGH();
PIN_LED_GREEN_LOW();
while (1){} //dummy loop for debugging
//TODO: system reset here
}
I expect the handler to be called when the button is pressed. If I call power_shutdown()
without polling the button (automatically after some time), then the EXTI0 handler is properly called when the button is pressed, however if the button has been pressed before (like in the normal use case), then further button presses don't trigger the handler.
Also if I force trigger a software interrupt with EXTI->SWIER1 = 0x1;
before the dummy loop the handler is only called if the button has not been pressed before. If the button has been pressed before, then the handler is not called even when the pending bit in EXTI->PR1
is set.
I do have default handler and hard fault handlers installed (they are not entered). This situation happens independently no matter if the debugger is connected or not. I know I am calling the function only once, because of the dummy loop at the end.
How to make EXTI trigger an interrupt if the button has been pressed before?
__HAL_RCC_SYSCFG_CLK_ENABLE();
at startup. \$\endgroup\$GPIOB->IDR & GPIO_IDR_ID0_Msk
, pullup is enabled. \$\endgroup\$