From 88770528bd9b7e0a2d0e6b51667d695a3475e9a0 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Fri, 30 Jun 2017 09:37:26 +0200 Subject: [PATCH 1/4] STM32 Fuly disable GPIO irq settings When disabling GPIO irq, also the falling / rising edge settings need to be reset (EXTI_RTSR and EXTI_FTSR registers). If not reset, the same EXTI line can be later enabled again with a wrong Rising / Falling configuration. This was especially seen and reported in ci-test tests-api-interruptin on NUCLEO_F446RE target where DIO2=PA_10 and DIO6=PB_10 were successively tested: as they are sharing the same EXTI_LINE (EXTI_10), this resulted in calling the irq_handler with wrong IRQ_FALL/IRQ_RAISE parameter and donothing being called in loop. --- targets/TARGET_STM/gpio_irq_api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/targets/TARGET_STM/gpio_irq_api.c b/targets/TARGET_STM/gpio_irq_api.c index a507a00164b..a465c13b6f8 100644 --- a/targets/TARGET_STM/gpio_irq_api.c +++ b/targets/TARGET_STM/gpio_irq_api.c @@ -290,6 +290,8 @@ void gpio_irq_enable(gpio_irq_t *obj) void gpio_irq_disable(gpio_irq_t *obj) { /* Clear EXTI line configuration */ + LL_EXTI_DisableRisingTrig_0_31(1 << STM_PIN(obj->pin)); + LL_EXTI_DisableFallingTrig_0_31(1 << STM_PIN(obj->pin)); LL_EXTI_DisableIT_0_31(1 << STM_PIN(obj->pin)); NVIC_DisableIRQ(obj->irq_n); NVIC_ClearPendingIRQ(obj->irq_n); From ade981dc9efab724fb1a29403b922dc98334b338 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Fri, 30 Jun 2017 13:23:08 +0200 Subject: [PATCH 2/4] STM32: Store and restore rising falling config of gpio_irq Now that rising / falling edge detection is disabled in the gpio_irq_disable function, we also need to restore it when gpio_irq_enable gets called. --- targets/TARGET_STM/gpio_irq_api.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/targets/TARGET_STM/gpio_irq_api.c b/targets/TARGET_STM/gpio_irq_api.c index a465c13b6f8..1ae8111ffc8 100644 --- a/targets/TARGET_STM/gpio_irq_api.c +++ b/targets/TARGET_STM/gpio_irq_api.c @@ -254,18 +254,23 @@ void gpio_irq_free(gpio_irq_t *obj) void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { + /* Enable / Disable Edge triggered interrupt and store event */ if (event == IRQ_RISE) { if (enable) { LL_EXTI_EnableRisingTrig_0_31(1 << STM_PIN(obj->pin)); + obj->event |= IRQ_RISE; } else { LL_EXTI_DisableRisingTrig_0_31(1 << STM_PIN(obj->pin)); + obj->event &= ~IRQ_RISE; } } if (event == IRQ_FALL) { if (enable) { LL_EXTI_EnableFallingTrig_0_31(1 << STM_PIN(obj->pin)); + obj->event |= IRQ_FALL; } else { LL_EXTI_DisableFallingTrig_0_31(1 << STM_PIN(obj->pin)); + obj->event &= ~IRQ_FALL; } } } @@ -284,6 +289,15 @@ void gpio_irq_enable(gpio_irq_t *obj) LL_EXTI_EnableIT_0_31(1 << pin_index); + /* Restore previous edge interrupt configuration if applicable */ + if (obj->event & IRQ_RISE) { + LL_EXTI_EnableRisingTrig_0_31(1 << STM_PIN(obj->pin)); + } + if (obj->event & IRQ_FALL) { + LL_EXTI_EnableFallingTrig_0_31(1 << STM_PIN(obj->pin)); + + } + NVIC_EnableIRQ(obj->irq_n); } @@ -295,5 +309,4 @@ void gpio_irq_disable(gpio_irq_t *obj) LL_EXTI_DisableIT_0_31(1 << STM_PIN(obj->pin)); NVIC_DisableIRQ(obj->irq_n); NVIC_ClearPendingIRQ(obj->irq_n); - obj->event = EDGE_NONE; } From cea91306de343c87d6209b72256889e699e7b576 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Fri, 30 Jun 2017 09:52:45 +0200 Subject: [PATCH 3/4] STM32: Raise error in case of spurious interrupt In case we've run through the entire GPIOs loop, withouth finding a matching interrupt, we're in the case of a spurious interrupt, let's raise an error to track it down. --- targets/TARGET_STM/gpio_irq_api.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/targets/TARGET_STM/gpio_irq_api.c b/targets/TARGET_STM/gpio_irq_api.c index 1ae8111ffc8..fd37f2cbe0f 100644 --- a/targets/TARGET_STM/gpio_irq_api.c +++ b/targets/TARGET_STM/gpio_irq_api.c @@ -90,8 +90,9 @@ static void handle_interrupt_in(uint32_t irq_index, uint32_t max_num_pin_line) if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - if (gpio_channel->channel_ids[gpio_idx] == 0) + if (gpio_channel->channel_ids[gpio_idx] == 0) { continue; + } // Check which edge has generated the irq if ((gpio->IDR & pin) == 0) { @@ -99,9 +100,11 @@ static void handle_interrupt_in(uint32_t irq_index, uint32_t max_num_pin_line) } else { irq_handler(gpio_channel->channel_ids[gpio_idx], IRQ_RISE); } + return; } } } + error("Unexpected Spurious interrupt, index %d\r\n", irq_index); } From 61648a53f5d57a54d29df039c5cff803c2b2f3e8 Mon Sep 17 00:00:00 2001 From: Laurent MEUNIER Date: Fri, 7 Jul 2017 17:27:46 +0200 Subject: [PATCH 4/4] Fix alignement --- targets/TARGET_STM/gpio_irq_api.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/targets/TARGET_STM/gpio_irq_api.c b/targets/TARGET_STM/gpio_irq_api.c index fd37f2cbe0f..f9c1f57990e 100644 --- a/targets/TARGET_STM/gpio_irq_api.c +++ b/targets/TARGET_STM/gpio_irq_api.c @@ -297,8 +297,7 @@ void gpio_irq_enable(gpio_irq_t *obj) LL_EXTI_EnableRisingTrig_0_31(1 << STM_PIN(obj->pin)); } if (obj->event & IRQ_FALL) { - LL_EXTI_EnableFallingTrig_0_31(1 << STM_PIN(obj->pin)); - + LL_EXTI_EnableFallingTrig_0_31(1 << STM_PIN(obj->pin)); } NVIC_EnableIRQ(obj->irq_n);