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
|
IRQs Yes
|
||||||
GPIO Yes
|
GPIO Yes
|
||||||
EXTI No
|
EXTI Yes
|
||||||
HSE Yes
|
HSE Yes
|
||||||
PLL Yes Tested @ 48MHz
|
PLL Yes Tested @ 48MHz
|
||||||
HSI Yes Not tested
|
HSI Yes Not tested
|
||||||
MSI Yes Not tested
|
MSI Yes Not tested
|
||||||
LSE Yes Not tested
|
LSE Yes Not tested
|
||||||
RCC Yes All registers defined, not all peripherals enabled
|
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
|
USART Yes
|
||||||
LPUART Yes full speed with HSE works, low power mode with LSE not implemented
|
LPUART Yes full speed with HSE works, low power mode with LSE not implemented
|
||||||
DMA No
|
DMA No
|
||||||
@ -102,7 +102,7 @@ SYSCFG
|
|||||||
------
|
------
|
||||||
|
|
||||||
System configuration controller. Can be used to remap memory or
|
System configuration controller. Can be used to remap memory or
|
||||||
manage external interrupts.
|
manage GPIO multiplexer for EXTI.
|
||||||
|
|
||||||
GPIO
|
GPIO
|
||||||
----
|
----
|
||||||
@ -123,6 +123,16 @@ IPCC
|
|||||||
Inter-processor communication controller. IPCC is used to exchange data
|
Inter-processor communication controller. IPCC is used to exchange data
|
||||||
between Cortex-M4 and Cortex-M0 CPUs.
|
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
|
Supported Boards
|
||||||
================
|
================
|
||||||
|
|
||||||
|
@ -32,43 +32,48 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define STM32WL5_NEXTI1 31
|
||||||
|
#define STM32WL5_EXTI1_MASK 0xffffffff
|
||||||
|
#define STM32WL5_NEXTI2 9
|
||||||
|
#define STM32WL5_EXTI2_MASK 0x000001ff
|
||||||
|
|
||||||
/* Register Offsets *********************************************************/
|
/* Register Offsets *********************************************************/
|
||||||
|
|
||||||
#define STM32WL5_EXTI_RTSR1_OFFSET 0x0000 /* Rising Trigger Selection 1 */
|
#define STM32WL5_EXTI_RTSR1_OFFSET 0x0000 /* Rising trigger selection 1 */
|
||||||
#define STM32WL5_EXTI_FTSR1_OFFSET 0x0004 /* Falling 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_SWIER1_OFFSET 0x0008 /* Software interrupt event 1 */
|
||||||
#define STM32WL5_EXTI_PR1_OFFSET 0x000c /* Pending 1 */
|
#define STM32WL5_EXTI_PR1_OFFSET 0x000c /* Pending 1 */
|
||||||
#define STM32WL5_EXTI_RTSR2_OFFSET 0x0020 /* Rising Trigger Selection 2 */
|
#define STM32WL5_EXTI_RTSR2_OFFSET 0x0020 /* Rising trigger selection 2 */
|
||||||
#define STM32WL5_EXTI_FTSR2_OFFSET 0x0024 /* Falling 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_SWIER2_OFFSET 0x0028 /* Software interrupt event 2 */
|
||||||
#define STM32WL5_EXTI_PR2_OFFSET 0x002c /* Pending 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_C1IMR1_OFFSET 0x0080 /* Interrupt mask 1 for cpu1 */
|
||||||
#define STM32WL5_EXTI_C1EMR1_OFFSET 0x0084 /* CPU Wakeup with Event Mask 1 for cpu1 */
|
#define STM32WL5_EXTI_C1EMR1_OFFSET 0x0084 /* Event mask 1 for cpu1 */
|
||||||
#define STM32WL5_EXTI_C1IMR2_OFFSET 0x0090 /* CPU Wakeup with Interrupt Mask 2 for cpu1 */
|
#define STM32WL5_EXTI_C1IMR2_OFFSET 0x0090 /* Interrupt mask 2 for cpu1 */
|
||||||
#define STM32WL5_EXTI_C1EMR2_OFFSET 0x0094 /* CPU Wakeup with Event Mask 2 for cpu1 */
|
#define STM32WL5_EXTI_C1EMR2_OFFSET 0x0094 /* Event mask 2 for cpu1 */
|
||||||
#define STM32WL5_EXTI_C2IMR1_OFFSET 0x00c0 /* CPU Wakeup with Interrupt Mask 1 for cpu2 */
|
#define STM32WL5_EXTI_C2IMR1_OFFSET 0x00c0 /* Interrupt mask 1 for cpu2 */
|
||||||
#define STM32WL5_EXTI_C2EMR1_OFFSET 0x00c4 /* CPU Wakeup with Event Mask 1 for cpu2 */
|
#define STM32WL5_EXTI_C2EMR1_OFFSET 0x00c4 /* Event mask 1 for cpu2 */
|
||||||
#define STM32WL5_EXTI_C2IMR2_OFFSET 0x00d0 /* CPU Wakeup with Interrupt Mask 2 for cpu2 */
|
#define STM32WL5_EXTI_C2IMR2_OFFSET 0x00d0 /* Interrupt mask 2 for cpu2 */
|
||||||
#define STM32WL5_EXTI_C2EMR2_OFFSET 0x00d4 /* CPU Wakeup with Event Mask 2 for cpu2 */
|
#define STM32WL5_EXTI_C2EMR2_OFFSET 0x00d4 /* Event mask 2 for cpu2 */
|
||||||
|
|
||||||
/* Register Addresses *******************************************************/
|
/* Register Addresses *******************************************************/
|
||||||
|
|
||||||
#define STM32WL5_EXTI_RTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR1_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_FTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR1_OFFSET)
|
||||||
#define STM32WL5_EXTI_SWIER1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER1_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_PR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR1_OFFSET)
|
||||||
#define STM32WL5_EXTI_RTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR2_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_FTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR2_OFFSET)
|
||||||
#define STM32WL5_EXTI_SWIER2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER2_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_PR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR2_OFFSET)
|
||||||
#define STM32WL5_EXTI_C1IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR1_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_C1EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR1_OFFSET)
|
||||||
#define STM32WL5_EXTI_C1IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR2_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_C1EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR2_OFFSET)
|
||||||
#define STM32WL5_EXTI_C2IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR1_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_C2EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR1_OFFSET)
|
||||||
#define STM32WL5_EXTI_C2IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR2_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_C2EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR2_OFFSET)
|
||||||
|
|
||||||
/* Register Bitfield Definitions ********************************************/
|
/* Register Bitfield Definitions ********************************************/
|
||||||
|
|
||||||
@ -103,4 +108,84 @@
|
|||||||
#define EXTI2_RADIOBSY (1 << 14) /* EXTI line 45: Radio busy wakeup */
|
#define EXTI2_RADIOBSY (1 << 14) /* EXTI line 45: Radio busy wakeup */
|
||||||
#define EXTI2_CDBGPWRUPREQ (1 << 15) /* EXTI line 46: Debug power-up request wakup */
|
#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 */
|
#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_EXTI_H */
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.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 ret = OK;
|
||||||
int exti;
|
|
||||||
(void)arg;
|
|
||||||
|
|
||||||
exti = irq - STM32WL5_IRQ_EXTI0;
|
/* Clear the pending interrupt */
|
||||||
DEBUGASSERT((exti >= 0) && (exti <= 15));
|
|
||||||
|
|
||||||
/* Clear the pending interrupt for both rising and falling edges. */
|
putreg32(0x0001, STM32WL5_EXTI_PR1);
|
||||||
|
|
||||||
putreg32(0x0001 << exti, STM32WL5_EXTI_PR1);
|
|
||||||
|
|
||||||
/* And dispatch the interrupt to the handler */
|
/* 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;
|
xcpt_t callback = g_gpio_handlers[0].callback;
|
||||||
void *cbarg = g_gpio_handlers[exti].arg;
|
void *cbarg = g_gpio_handlers[0].arg;
|
||||||
|
|
||||||
ret = callback(irq, context, cbarg);
|
ret = callback(irq, context, cbarg);
|
||||||
}
|
}
|
||||||
@ -91,6 +85,144 @@ static int stm32wl5_exti0_15_isr(int irq, void *context, FAR void *arg)
|
|||||||
return ret;
|
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
|
* 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,
|
int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
|
||||||
bool event, xcpt_t func, void *arg)
|
bool event, xcpt_t func, void *arg)
|
||||||
{
|
{
|
||||||
|
struct gpio_callback_s *shared_cbs;
|
||||||
uint32_t pin = pinset & GPIO_PIN_MASK;
|
uint32_t pin = pinset & GPIO_PIN_MASK;
|
||||||
uint32_t exti = 1 << pin;
|
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].callback = func;
|
||||||
g_gpio_handlers[pin].arg = arg;
|
g_gpio_handlers[pin].arg = arg;
|
||||||
@ -132,12 +315,27 @@ int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge,
|
|||||||
|
|
||||||
if (func)
|
if (func)
|
||||||
{
|
{
|
||||||
irq_attach(irq, stm32wl5_exti0_15_isr, NULL);
|
irq_attach(irq, handler, NULL);
|
||||||
up_enable_irq(irq);
|
up_enable_irq(irq);
|
||||||
}
|
}
|
||||||
else
|
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
|
/* 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 ? 0 : exti,
|
||||||
func ? exti : 0);
|
func ? exti : 0);
|
||||||
|
|
||||||
|
/* Return the old IRQ handler */
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
@ -279,6 +279,30 @@ int stm32wl5_configgpio(uint32_t cfgset)
|
|||||||
|
|
||||||
putreg32(regval, base + STM32WL5_GPIO_OTYPER_OFFSET);
|
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);
|
leave_critical_section(flags);
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user