stm32wl5: add EXTI support for GPIO
This patch implements working support for EXTI GPIO. Signed-off-by: Michał Łyszczek <michal.lyszczek@bofc.pl> -- 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:)
This commit is contained in:
parent
cb8c992914
commit
288b57d5ca
@ -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
|
||||
================
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user