From dea25437c736f92a3ff346bd38b71413fcd865ee Mon Sep 17 00:00:00 2001 From: Joshua DeWeese Date: Mon, 13 Mar 2023 13:39:16 -0400 Subject: [PATCH] cpu/stm32/periph/timer: fix clobered IRQ flag The STM32 periph_timer driver reads the timer's status flags, then clears them all. It is possible that a timer interrupt could occur between reading the flag and clearing it. This would lead to a lost interrupt. The timer's status flags can be cleared by software, but can only be set by the hardware. This patch takes advantage of this by only clearing the flags it knows are set. The rest of the flags are set, which doesn't actually change their state. --- cpu/stm32/periph/timer.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cpu/stm32/periph/timer.c b/cpu/stm32/periph/timer.c index 6f5004177a..92660fa755 100644 --- a/cpu/stm32/periph/timer.c +++ b/cpu/stm32/periph/timer.c @@ -267,7 +267,12 @@ static inline void irq_handler(tim_t tim) { uint32_t top = dev(tim)->ARR; uint32_t status = dev(tim)->SR & dev(tim)->DIER; - dev(tim)->SR = 0; + + /* clear interrupts which we are about to service */ + /* Note, the flags in the SR register can be cleared by software, but + * setting them has no effect on the register. Only the hardware can set + * them. */ + dev(tim)->SR = ~status; for (unsigned int i = 0; status; i++) { uint32_t msk = TIM_SR_CC1IF << i;