From 6f793fbb5a9941a59595f74ca2e67ae2d39ae6de Mon Sep 17 00:00:00 2001 From: Chun-Chieh Li Date: Fri, 7 Feb 2020 15:48:57 +0800 Subject: [PATCH] M2351: Fix GPIO rising/falling edge interrupts cannot exist simultaneously --- .../TARGET_M2351/gpio_irq_api.c | 41 +++++++++++-------- targets/TARGET_NUVOTON/TARGET_M2351/objects.h | 1 + 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c index a6b2a8be55..5a6e2f8c7a 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c @@ -23,6 +23,7 @@ #include "pinmap.h" #include "PeripheralPins.h" #include "nu_bitutil.h" +#include "mbed_assert.h" #define NU_MAX_PIN_PER_PORT 16 @@ -89,6 +90,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 } obj->pin = pin; + obj->irq_types = 0; obj->irq_handler = (uint32_t) handler; obj->irq_id = id; @@ -156,27 +158,32 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); GPIO_T *gpio_base = NU_PORT_BASE(port_index); + /* We assume BSP has such coding so that we can easily add/remove either irq type. */ + MBED_STATIC_ASSERT(GPIO_INT_BOTH_EDGE == (GPIO_INT_RISING | GPIO_INT_FALLING), + "GPIO_INT_BOTH_EDGE must be bitwise OR of GPIO_INT_RISING and GPIO_INT_FALLING"); + uint32_t irq_type; switch (event) { - case IRQ_RISE: - if (enable) { - GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING); - } else { - gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index); - } - break; + case IRQ_RISE: + irq_type = GPIO_INT_RISING; + break; - case IRQ_FALL: - if (enable) { - GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING); - } else { - gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index); - } - break; + case IRQ_FALL: + irq_type = GPIO_INT_FALLING; + break; - case IRQ_NONE: - default: - break; + default: + irq_type = 0; } + + /* We can handle invalid/null irq type. */ + if (enable) { + obj->irq_types |= irq_type; + } else { + obj->irq_types &= ~irq_type; + } + + /* Update irq types */ + GPIO_EnableInt(gpio_base, pin_index, obj->irq_types); } void gpio_irq_enable(gpio_irq_t *obj) diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/objects.h b/targets/TARGET_NUVOTON/TARGET_M2351/objects.h index 5bef7dbae2..5755be0f0e 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/objects.h +++ b/targets/TARGET_NUVOTON/TARGET_M2351/objects.h @@ -29,6 +29,7 @@ extern "C" { struct gpio_irq_s { PinName pin; + uint32_t irq_types; uint32_t irq_handler; uint32_t irq_id; struct gpio_irq_s *next;