From b22ad155d56e272eb846c21209cfe7524f17da23 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 20 Jan 2021 13:48:32 -0600 Subject: [PATCH] platform/technic_hub: fix race condition in TIM2 irq handler This fixes a race condition where an interrupt status flag is set while the interrupt handler is running. We were clearing all flags each time the handler ran but now we only clear the flags we have handled. This was triggered when CCR1 was set to 3, causing the green LED to turn on and stay on all of the time. Fixes: pybricks/support#224 --- lib/pbio/platform/technic_hub/platform.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/pbio/platform/technic_hub/platform.c b/lib/pbio/platform/technic_hub/platform.c index 9515fece8..e49296e6d 100644 --- a/lib/pbio/platform/technic_hub/platform.c +++ b/lib/pbio/platform/technic_hub/platform.c @@ -205,12 +205,14 @@ const pbdrv_pwm_stm32_tim_platform_data_t // the GPIOs in the timer interrupt handler. void TIM2_IRQHandler(void) { uint32_t sr = TIM2->SR; + uint32_t handled = TIM_SR_UIF; // green LED if (TIM2->CCR1 == 0 || sr & TIM_SR_CC1IF) { // If channel 1 duty cycle is 0 or we have reached the CC1 count, // turn the GPIO off GPIOA->BRR = GPIO_BRR_BR11; + handled |= TIM_SR_CC1IF; } else if (sr & TIM_SR_UIF) { // otherwise if it is the start of the next PWM period turn the GPIO on GPIOA->BSRR = GPIO_BSRR_BS11; @@ -221,13 +223,14 @@ void TIM2_IRQHandler(void) { // If channel 2 duty cycle is 0 or we have reached the CC2 count, // turn the GPIO off GPIOB->BRR = GPIO_BRR_BR15; + handled |= TIM_SR_CC2IF; } else if (sr & TIM_SR_UIF) { // otherwise if it is the start of the next PWM period turn the GPIO on GPIOB->BSRR = GPIO_BSRR_BS15; } // clear interrupts - TIM2->SR = 0; + TIM2->SR &= ~handled; } // Reset