I'm learning STM32 by a NUCLEO-L053R8 board (STM32L053R8T6 - Cortex M0+).
I want to put device to sleep and wake it by either an interrupt or an event.// Keil uVision V5.31.0.0 int main() { // Clock and peripherals init // UART init (baud rate, GPIO, etc. are initialized before) EXTI->IMR &= ~EXTI_IMR_IM26; EXTI->EMR |= EXTI_EMR_EM26; USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE; RCC->IOPENR |= RCC_IOPENR_GPIOCEN; RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; GPIOC->PUPDR = (GPIOC->PUPDR & GPIO_PUPDR_PUPD13_Msk) | GPIO_PUPDR_PUPD13_0; // PC13 - user button GPIOC->MODER &= ~GPIO_MODER_MODE13; SYSCFG->EXTICR[3] = (SYSCFG->EXTICR[3] & SYSCFG_EXTICR4_EXTI13_Msk) | SYSCFG_EXTICR4_EXTI13_PC; EXTI->EMR |= EXTI_EMR_EM13; EXTI->FTSR |= EXTI_FTSR_FT13; EXTI->RTSR &= ~EXTI_RTSR_RT13; while (1) { SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; __SEV(); __WFE(); __WFE(); SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; while ((GPIOC->IDR & GPIO_IDR_ID13) == 0) { // Process GPIO } if (UART2_NewDataAvailable()) { // Process UART } } }
// Keil uVision V5.31.0.0 int main() { // Clock and peripherals init // UART init (baud rate, GPIO, etc. are initialized before) EXTI->IMR &= ~EXTI_IMR_IM26; EXTI->EMR |= EXTI_EMR_EM26; USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE; RCC->IOPENR |= RCC_IOPENR_GPIOCEN; RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; GPIOC->PUPDR = (GPIOC->PUPDR & GPIO_PUPDR_PUPD13_Msk) | GPIO_PUPDR_PUPD13_0; // PC13 - user button GPIOC->MODER &= ~GPIO_MODER_MODE13; SYSCFG->EXTICR[3] = (SYSCFG->EXTICR[3] & SYSCFG_EXTICR4_EXTI13_Msk) | SYSCFG_EXTICR4_EXTI13_PC; EXTI->EMR |= EXTI_EMR_EM13; EXTI->FTSR |= EXTI_FTSR_FT13; EXTI->RTSR &= ~EXTI_RTSR_RT13; while (1) { SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; __SEV(); __WFE(); __WFE(); SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; while ((GPIOC->IDR & GPIO_IDR_ID13) == 0) { // Process GPIO } if (UART2_NewDataAvailable()) { // Process UART } } }
When I press button, device wakes up and processes GPIO and UART once, then goes to sleep. There is no need to clear any flag as the channel is configured as event (EM13).
However, sending a character to UART doesn't wake CPU.
If I set SEVONPEND bit, clear both IM26 and EM26, and leave NVIC as default (no priority or IRQ enabled for USART2), sending a character to UART wakes device once and no more; because NVIC channel pending bit is set and should be cleared manually. I prefer to use event so I shouldn't clear pending flag each time.
Why UART doesn't wake the CPU when configured as event?
Sorry! I'm new to ARM and a little confused about documentations. :)
I thought it is related to NVIC so I posted my question here but you're right; It is related to EXTI peripheral which is for STM32 not ARM core.
Here is the same question in ST community with the answer.