From 288b57d5ca7b3d79d343f50d7d562f16d91c2861 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=81yszczek?= Date: Sun, 12 Jun 2022 14:06:22 +0200 Subject: [PATCH] stm32wl5: add EXTI support for GPIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch implements working support for EXTI GPIO. Signed-off-by: Michał Łyszczek -- v1 -> v2: Suggested by: Petro Karashchenko - change (1 << n) to (1 << (n)) in macro definition - change 1 << X to (1 << X) in code - fix alignment v2 -> v3: Suggested by: Petro Karashchenko - I was supposed to change (1 << pin) to 1 << pin, not the other way around:) --- .../platforms/arm/stm32wl5/index.rst | 16 +- .../arm/src/stm32wl5/hardware/stm32wl5_exti.h | 149 ++++++++--- arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c | 232 ++++++++++++++++-- arch/arm/src/stm32wl5/stm32wl5_gpio.c | 24 ++ 4 files changed, 370 insertions(+), 51 deletions(-) diff --git a/Documentation/platforms/arm/stm32wl5/index.rst b/Documentation/platforms/arm/stm32wl5/index.rst index f52cc39938..3099ebaa8f 100644 --- a/Documentation/platforms/arm/stm32wl5/index.rst +++ b/Documentation/platforms/arm/stm32wl5/index.rst @@ -30,14 +30,14 @@ Peripheral Support Notes ========== ======= ===== IRQs Yes GPIO Yes -EXTI No +EXTI Yes HSE Yes PLL Yes Tested @ 48MHz HSI Yes Not tested MSI Yes Not tested LSE Yes Not tested RCC Yes All registers defined, not all peripherals enabled -SYSCFG Yes All registers defined, remapping not tested +SYSCFG Yes All registers defined, GPIO EXTI works, remapping not tested USART Yes LPUART Yes full speed with HSE works, low power mode with LSE not implemented DMA No @@ -102,7 +102,7 @@ SYSCFG ------ System configuration controller. Can be used to remap memory or -manage external interrupts. +manage GPIO multiplexer for EXTI. GPIO ---- @@ -123,6 +123,16 @@ IPCC Inter-processor communication controller. IPCC is used to exchange data between Cortex-M4 and Cortex-M0 CPUs. +EXTI +---- + +Extended interrupts and event controller. Extends interrupts not provided +by NVIC. For example, there is only one interrupt for GPIO5..9 in NVIC, +but thanks to EXTI we can differentiate which GPIO caused interrupt. Such +interrupt first goes through EXTI and is then forwarded to main NVIC. + +EXTI for gpio can be enabled via `stm32wl5_gpiosetevent` function. + Supported Boards ================ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h index 9b9b211196..75273550bb 100644 --- a/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h @@ -32,43 +32,48 @@ * Pre-processor Definitions ****************************************************************************/ +#define STM32WL5_NEXTI1 31 +#define STM32WL5_EXTI1_MASK 0xffffffff +#define STM32WL5_NEXTI2 9 +#define STM32WL5_EXTI2_MASK 0x000001ff + /* Register Offsets *********************************************************/ -#define STM32WL5_EXTI_RTSR1_OFFSET 0x0000 /* Rising Trigger Selection 1 */ -#define STM32WL5_EXTI_FTSR1_OFFSET 0x0004 /* Falling Trigger Selection 1 */ -#define STM32WL5_EXTI_SWIER1_OFFSET 0x0008 /* Software Interrupt Event 1 */ -#define STM32WL5_EXTI_PR1_OFFSET 0x000c /* Pending 1 */ -#define STM32WL5_EXTI_RTSR2_OFFSET 0x0020 /* Rising Trigger Selection 2 */ -#define STM32WL5_EXTI_FTSR2_OFFSET 0x0024 /* Falling Trigger Selection 2 */ -#define STM32WL5_EXTI_SWIER2_OFFSET 0x0028 /* Software Interrupt Event 2 */ -#define STM32WL5_EXTI_PR2_OFFSET 0x002c /* Pending 2 */ -#define STM32WL5_EXTI_C1IMR1_OFFSET 0x0080 /* CPU Wakeup with Interrupt Mask 1 for cpu1 */ -#define STM32WL5_EXTI_C1EMR1_OFFSET 0x0084 /* CPU Wakeup with Event Mask 1 for cpu1 */ -#define STM32WL5_EXTI_C1IMR2_OFFSET 0x0090 /* CPU Wakeup with Interrupt Mask 2 for cpu1 */ -#define STM32WL5_EXTI_C1EMR2_OFFSET 0x0094 /* CPU Wakeup with Event Mask 2 for cpu1 */ -#define STM32WL5_EXTI_C2IMR1_OFFSET 0x00c0 /* CPU Wakeup with Interrupt Mask 1 for cpu2 */ -#define STM32WL5_EXTI_C2EMR1_OFFSET 0x00c4 /* CPU Wakeup with Event Mask 1 for cpu2 */ -#define STM32WL5_EXTI_C2IMR2_OFFSET 0x00d0 /* CPU Wakeup with Interrupt Mask 2 for cpu2 */ -#define STM32WL5_EXTI_C2EMR2_OFFSET 0x00d4 /* CPU Wakeup with Event Mask 2 for cpu2 */ +#define STM32WL5_EXTI_RTSR1_OFFSET 0x0000 /* Rising trigger selection 1 */ +#define STM32WL5_EXTI_FTSR1_OFFSET 0x0004 /* Falling trigger selection 1 */ +#define STM32WL5_EXTI_SWIER1_OFFSET 0x0008 /* Software interrupt event 1 */ +#define STM32WL5_EXTI_PR1_OFFSET 0x000c /* Pending 1 */ +#define STM32WL5_EXTI_RTSR2_OFFSET 0x0020 /* Rising trigger selection 2 */ +#define STM32WL5_EXTI_FTSR2_OFFSET 0x0024 /* Falling trigger selection 2 */ +#define STM32WL5_EXTI_SWIER2_OFFSET 0x0028 /* Software interrupt event 2 */ +#define STM32WL5_EXTI_PR2_OFFSET 0x002c /* Pending 2 */ +#define STM32WL5_EXTI_C1IMR1_OFFSET 0x0080 /* Interrupt mask 1 for cpu1 */ +#define STM32WL5_EXTI_C1EMR1_OFFSET 0x0084 /* Event mask 1 for cpu1 */ +#define STM32WL5_EXTI_C1IMR2_OFFSET 0x0090 /* Interrupt mask 2 for cpu1 */ +#define STM32WL5_EXTI_C1EMR2_OFFSET 0x0094 /* Event mask 2 for cpu1 */ +#define STM32WL5_EXTI_C2IMR1_OFFSET 0x00c0 /* Interrupt mask 1 for cpu2 */ +#define STM32WL5_EXTI_C2EMR1_OFFSET 0x00c4 /* Event mask 1 for cpu2 */ +#define STM32WL5_EXTI_C2IMR2_OFFSET 0x00d0 /* Interrupt mask 2 for cpu2 */ +#define STM32WL5_EXTI_C2EMR2_OFFSET 0x00d4 /* Event mask 2 for cpu2 */ /* Register Addresses *******************************************************/ -#define STM32WL5_EXTI_RTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR1_OFFSET) -#define STM32WL5_EXTI_FTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR1_OFFSET) -#define STM32WL5_EXTI_SWIER1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER1_OFFSET) -#define STM32WL5_EXTI_PR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR1_OFFSET) -#define STM32WL5_EXTI_RTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR2_OFFSET) -#define STM32WL5_EXTI_FTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR2_OFFSET) -#define STM32WL5_EXTI_SWIER2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER2_OFFSET) -#define STM32WL5_EXTI_PR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR2_OFFSET) -#define STM32WL5_EXTI_C1IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR1_OFFSET) -#define STM32WL5_EXTI_C1EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR1_OFFSET) -#define STM32WL5_EXTI_C1IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR2_OFFSET) -#define STM32WL5_EXTI_C1EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR2_OFFSET) -#define STM32WL5_EXTI_C2IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR1_OFFSET) -#define STM32WL5_EXTI_C2EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR1_OFFSET) -#define STM32WL5_EXTI_C2IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR2_OFFSET) -#define STM32WL5_EXTI_C2EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR2_OFFSET) +#define STM32WL5_EXTI_RTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR1_OFFSET) +#define STM32WL5_EXTI_FTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR1_OFFSET) +#define STM32WL5_EXTI_SWIER1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER1_OFFSET) +#define STM32WL5_EXTI_PR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR1_OFFSET) +#define STM32WL5_EXTI_RTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR2_OFFSET) +#define STM32WL5_EXTI_FTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR2_OFFSET) +#define STM32WL5_EXTI_SWIER2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER2_OFFSET) +#define STM32WL5_EXTI_PR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR2_OFFSET) +#define STM32WL5_EXTI_C1IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR1_OFFSET) +#define STM32WL5_EXTI_C1EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR1_OFFSET) +#define STM32WL5_EXTI_C1IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR2_OFFSET) +#define STM32WL5_EXTI_C1EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR2_OFFSET) +#define STM32WL5_EXTI_C2IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR1_OFFSET) +#define STM32WL5_EXTI_C2EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR1_OFFSET) +#define STM32WL5_EXTI_C2IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR2_OFFSET) +#define STM32WL5_EXTI_C2EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR2_OFFSET) /* Register Bitfield Definitions ********************************************/ @@ -103,4 +108,84 @@ #define EXTI2_RADIOBSY (1 << 14) /* EXTI line 45: Radio busy wakeup */ #define EXTI2_CDBGPWRUPREQ (1 << 15) /* EXTI line 46: Debug power-up request wakup */ +/* Rising Trigger selection register */ + +#define EXTI_RTSR1_BIT(n) (1 << (n)) /* 1=Rising trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_RTSR1_SHIFT (0) /* Bits 0-X: Rising trigger event configuration bit for all lines */ +#define EXTI_RTSR1_MASK (0x0061ffff) + +#define EXTI_RTSR2_BIT(n) (1 << (n)) /* 1=Rising trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_RTSR2_SHIFT (0) /* Bits 0-X: Rising trigger event configuration bit for all lines */ +#define EXTI_RTSR2_MASK (0x00002304) + +/* Falling Trigger selection register */ + +#define EXTI_FTSR1_BIT(n) (1 << (n)) /* 1=Falling trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_FTSR1_SHIFT (0) /* Bits 0-X: Falling trigger event configuration bitfor all lines */ +#define EXTI_FTSR1_MASK (0x0061ffff) + +#define EXTI_FTSR2_BIT(n) (1 << (n)) /* 1=Falling trigger enabled (for Event and Interrupt) for input line */ +#define EXTI_FTSR2_SHIFT (0) /* Bits 0-X: Falling trigger event configuration bitfor all lines */ +#define EXTI_FTSR2_MASK (0x00002304) + +/* Software interrupt event register */ + +#define EXTI_SWIER1_BIT(n) (1 << (n)) /* 1=Sets the corresponding pending bit in EXTI_PR */ +#define EXTI_SWIER1_SHIFT (0) /* Bits 0-X: Software Interrupt for all lines */ +#define EXTI_SWIER1_MASK (0x0061ffff) + +#define EXTI_SWIER2_BIT(n) (1 << (n)) /* 1=Sets the corresponding pending bit in EXTI_PR */ +#define EXTI_SWIER2_SHIFT (0) /* Bits 0-X: Software Interrupt for all lines */ +#define EXTI_SWIER2_MASK (0x00002304) + +/* Pending register */ + +#define EXTI_PR1_BIT(n) (1 << (n)) /* 1=Selected trigger request occurred */ +#define EXTI_PR1_SHIFT (0) /* Bits 0-X: Pending bit for all lines */ +#define EXTI_PR1_MASK (0x0061ffff) + +#define EXTI_PR2_BIT(n) (1 << (n)) /* 1=Selected trigger request occurred */ +#define EXTI_PR2_SHIFT (0) /* Bits 0-X: Pending bit for all lines */ +#define EXTI_PR2_MASK (0x00002304) + +/* Interrupt mask register */ + +#define EXTI_C1IMR1_BIT(n) (1 << (n)) /* 1=Interrupt request from line x is not masked */ +#define EXTI_C1IMR1_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */ +#define EXTI_C1IMR1_MASK (0xffffffff) + +#define EXTI_C1IMR2_BIT(n) (1 << (n)) /* 1=Interrupt request from line x is not masked */ +#define EXTI_C1IMR2_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */ +#define EXTI_C1IMR2_MASK (0x007effff) + +/* Event mask register */ + +#define EXTI_C1EMR1_BIT(n) (1 << (n)) /* 1=Event request from line x is not mask */ +#define EXTI_C1EMR1_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */ +#define EXTI_C1EMR1_MASK (0x00007ff4) + +#define EXTI_C1EMR2_BIT(n) (1 << (n)) /* 1=Event request from line x is not mask */ +#define EXTI_C1EMR2_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */ +#define EXTI_C1EMR2_MASK (0x00000300) + +/* Interrupt mask register */ + +#define EXTI_C2IMR1_BIT(n) (1 << (n)) /* 1=Interrupt request from line x is not masked */ +#define EXTI_C2IMR1_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */ +#define EXTI_C2IMR1_MASK (0xffffffff) + +#define EXTI_C2IMR2_BIT(n) (1 << (n)) /* 1=Interrupt request from line x is not masked */ +#define EXTI_C2IMR2_SHIFT (0) /* Bits 0-X: Interrupt Mask for all lines */ +#define EXTI_C2IMR2_MASK (0x007effff) + +/* Event mask register */ + +#define EXTI_C2EMR1_BIT(n) (1 << (n)) /* 1=Event request from line x is not mask */ +#define EXTI_C2EMR1_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */ +#define EXTI_C2EMR1_MASK (0x00007ff4) + +#define EXTI_C2EMR2_BIT(n) (1 << (n)) /* 1=Event request from line x is not mask */ +#define EXTI_C2EMR2_SHIFT (0) /* Bits Bits 0-X: Event Mask for all lines */ +#define EXTI_C2EMR2_MASK (0x00000300) + #endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_EXTI_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c b/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c index 2da29516a5..153a409996 100644 --- a/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c +++ b/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -62,28 +61,23 @@ static struct gpio_callback_s g_gpio_handlers[16]; ****************************************************************************/ /**************************************************************************** - * Interrupt Service Routine - Dispatcher + * Interrupt Service Routines - Dispatchers ****************************************************************************/ -static int stm32wl5_exti0_15_isr(int irq, void *context, FAR void *arg) +static int stm32wl5_exti0_isr(int irq, void *context, void *arg) { int ret = OK; - int exti; - (void)arg; - exti = irq - STM32WL5_IRQ_EXTI0; - DEBUGASSERT((exti >= 0) && (exti <= 15)); + /* Clear the pending interrupt */ - /* Clear the pending interrupt for both rising and falling edges. */ - - putreg32(0x0001 << exti, STM32WL5_EXTI_PR1); + putreg32(0x0001, STM32WL5_EXTI_PR1); /* And dispatch the interrupt to the handler */ - if (g_gpio_handlers[exti].callback != NULL) + if (g_gpio_handlers[0].callback != NULL) { - xcpt_t callback = g_gpio_handlers[exti].callback; - void *cbarg = g_gpio_handlers[exti].arg; + xcpt_t callback = g_gpio_handlers[0].callback; + void *cbarg = g_gpio_handlers[0].arg; ret = callback(irq, context, cbarg); } @@ -91,6 +85,144 @@ static int stm32wl5_exti0_15_isr(int irq, void *context, FAR void *arg) return ret; } +static int stm32wl5_exti1_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0002, STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[1].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[1].callback; + void *cbarg = g_gpio_handlers[1].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +static int stm32wl5_exti2_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0004, STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[2].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[2].callback; + void *cbarg = g_gpio_handlers[2].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +static int stm32wl5_exti3_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0008, STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[3].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[3].callback; + void *cbarg = g_gpio_handlers[3].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +static int stm32wl5_exti4_isr(int irq, void *context, void *arg) +{ + int ret = OK; + + /* Clear the pending interrupt */ + + putreg32(0x0010, STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[4].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[4].callback; + void *cbarg = g_gpio_handlers[4].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +static int stm32wl5_exti_multiisr(int irq, void *context, void *arg, + int first, int last) +{ + uint32_t pr; + int pin; + int ret = OK; + + /* Examine the state of each pin in the group */ + + pr = getreg32(STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + for (pin = first; pin <= last; pin++) + { + /* Is an interrupt pending on this pin? */ + + uint32_t mask = 1 << pin; + if ((pr & mask) != 0) + { + /* Clear the pending interrupt */ + + putreg32(mask, STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[pin].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[pin].callback; + void *cbarg = g_gpio_handlers[pin].arg; + int tmp; + + tmp = callback(irq, context, cbarg); + if (tmp < 0) + { + ret = tmp; + } + } + } + } + + return ret; +} + +static int stm32wl5_exti95_isr(int irq, void *context, void *arg) +{ + return stm32wl5_exti_multiisr(irq, context, arg, 5, 9); +} + +static int stm32wl5_exti1510_isr(int irq, void *context, void *arg) +{ + return stm32wl5_exti_multiisr(irq, context, arg, 10, 15); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -121,9 +253,60 @@ static int stm32wl5_exti0_15_isr(int irq, void *context, FAR void *arg) int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, bool event, xcpt_t func, void *arg) { + struct gpio_callback_s *shared_cbs; uint32_t pin = pinset & GPIO_PIN_MASK; uint32_t exti = 1 << pin; - int irq = STM32WL5_IRQ_EXTI0 + pin; + int irq; + xcpt_t handler; + int nshared; + int i; + + /* Select the interrupt handler for this EXTI pin */ + + if (pin < 5) + { + irq = pin + STM32WL5_IRQ_EXTI0; + nshared = 1; + shared_cbs = &g_gpio_handlers[pin]; + switch (pin) + { + case 0: + handler = stm32wl5_exti0_isr; + break; + + case 1: + handler = stm32wl5_exti1_isr; + break; + + case 2: + handler = stm32wl5_exti2_isr; + break; + + case 3: + handler = stm32wl5_exti3_isr; + break; + + default: + handler = stm32wl5_exti4_isr; + break; + } + } + else if (pin < 10) + { + irq = STM32WL5_IRQ_EXTI95; + handler = stm32wl5_exti95_isr; + shared_cbs = &g_gpio_handlers[5]; + nshared = 5; + } + else + { + irq = STM32WL5_IRQ_EXTI1510; + handler = stm32wl5_exti1510_isr; + shared_cbs = &g_gpio_handlers[10]; + nshared = 6; + } + + /* Get the previous GPIO IRQ handler; Save the new IRQ handler. */ g_gpio_handlers[pin].callback = func; g_gpio_handlers[pin].arg = arg; @@ -132,12 +315,27 @@ int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, if (func) { - irq_attach(irq, stm32wl5_exti0_15_isr, NULL); + irq_attach(irq, handler, NULL); up_enable_irq(irq); } else { - up_disable_irq(irq); + /* Only disable IRQ if shared handler does not have any active + * callbacks. + */ + + for (i = 0; i < nshared; i++) + { + if (shared_cbs[i].callback != NULL) + { + break; + } + } + + if (i == nshared) + { + up_disable_irq(irq); + } } /* Configure GPIO, enable EXTI line enabled if event or interrupt is @@ -169,5 +367,7 @@ int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, func ? 0 : exti, func ? exti : 0); + /* Return the old IRQ handler */ + return OK; } diff --git a/arch/arm/src/stm32wl5/stm32wl5_gpio.c b/arch/arm/src/stm32wl5/stm32wl5_gpio.c index 1a570cdf64..122ca63fd7 100644 --- a/arch/arm/src/stm32wl5/stm32wl5_gpio.c +++ b/arch/arm/src/stm32wl5/stm32wl5_gpio.c @@ -279,6 +279,30 @@ int stm32wl5_configgpio(uint32_t cfgset) putreg32(regval, base + STM32WL5_GPIO_OTYPER_OFFSET); + /* Otherwise, it is an input pin. Should it configured as an + * EXTI interrupt? + */ + + if (pinmode != GPIO_MODER_OUTPUT && (cfgset & GPIO_EXTI) != 0) + { + /* The selection of the EXTI line source is performed through the EXTIx + * bits in the SYSCFG_EXTICRx registers. + */ + + uint32_t regaddr; + int shift; + + /* Set the bits in the SYSCFG EXTICR register */ + + regaddr = STM32WL5_SYSCFG_EXTICR(pin); + regval = getreg32(regaddr); + shift = SYSCFG_EXTICR_EXTI_SHIFT(pin); + regval &= ~(SYSCFG_EXTICR_PORT_MASK << shift); + regval |= (((uint32_t)port) << shift); + + putreg32(regval, regaddr); + } + leave_critical_section(flags); return OK; }