xtensa/esp32s3: Add support for GPIO pin interrupts
Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
parent
0e67dc8637
commit
024364ebbd
@ -25,6 +25,12 @@
|
||||
#ifndef __ARCH_XTENSA_INCLUDE_ESP32S3_IRQ_H
|
||||
#define __ARCH_XTENSA_INCLUDE_ESP32S3_IRQ_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@ -309,19 +315,20 @@
|
||||
|
||||
#define ESP32S3_NIRQ_PERIPH ESP32S3_NPERIPHERALS
|
||||
|
||||
/* Second level GPIO interrupts. GPIO interrupts are decoded and dispatched
|
||||
* as a second level of decoding: The first level dispatches to the GPIO
|
||||
* interrupt handler. The second to the decoded GPIO interrupt handler.
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
|
||||
/* Second level GPIO interrupts. GPIO interrupts are decoded and dispatched
|
||||
* as a second level of decoding: The first level dispatches to the GPIO
|
||||
* interrupt handler. The second to the decoded GPIO interrupt handler.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
# define ESP32S3_NIRQ_GPIO 40
|
||||
# define ESP32S3_FIRST_GPIOIRQ (XTENSA_NIRQ_INTERNAL + ESP32S3_NIRQ_PERIPH)
|
||||
# define ESP32S3_LAST_GPIOIRQ (ESP32S3_FIRST_GPIOIRQ + ESP32S3_NIRQ_GPIO - 1)
|
||||
# define ESP32S3_PIN2IRQ(p) ((p) + ESP32S3_FIRST_GPIOIRQ)
|
||||
# define ESP32S3_IRQ2PIN(i) ((i) - ESP32S3_FIRST_GPIOIRQ)
|
||||
# define ESP32S3_NIRQ_GPIO 49
|
||||
# define ESP32S3_FIRST_GPIOIRQ (XTENSA_NIRQ_INTERNAL + ESP32S3_NIRQ_PERIPH)
|
||||
# define ESP32S3_LAST_GPIOIRQ (ESP32S3_FIRST_GPIOIRQ + ESP32S3_NIRQ_GPIO - 1)
|
||||
# define ESP32S3_PIN2IRQ(p) ((p) + ESP32S3_FIRST_GPIOIRQ)
|
||||
# define ESP32S3_IRQ2PIN(i) ((i) - ESP32S3_FIRST_GPIOIRQ)
|
||||
#else
|
||||
# define ESP32S3_NIRQ_GPIO 0
|
||||
# define ESP32S3_NIRQ_GPIO 0
|
||||
#endif
|
||||
|
||||
/* Total number of interrupts */
|
||||
|
@ -511,6 +511,12 @@ config ESP32S3_SPIRAM_IGNORE_NOTFOUND
|
||||
|
||||
endmenu # SPI RAM Configuration
|
||||
|
||||
config ESP32S3_GPIO_IRQ
|
||||
bool "GPIO pin interrupts"
|
||||
default n
|
||||
---help---
|
||||
Enable support for interrupting GPIO pins.
|
||||
|
||||
menu "UART Configuration"
|
||||
depends on ESP32S3_UART
|
||||
|
||||
|
@ -49,6 +49,10 @@
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
static int g_gpio_cpuint;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -74,6 +78,94 @@ static inline bool is_valid_gpio(uint32_t pin)
|
||||
return pin <= 21 || (pin >= 26 && pin < ESP32S3_NPINS);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: gpio_dispatch
|
||||
*
|
||||
* Description:
|
||||
* Second level dispatch for GPIO interrupt handling.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - GPIO IRQ number.
|
||||
* status - Value from the GPIO interrupt status clear register.
|
||||
* regs - Saved CPU context.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
static void gpio_dispatch(int irq, uint32_t status, uint32_t *regs)
|
||||
{
|
||||
uint32_t mask;
|
||||
int i;
|
||||
|
||||
/* Check each bit in the status register */
|
||||
|
||||
for (i = 0; i < 32 && status != 0; i++)
|
||||
{
|
||||
/* Check if there is an interrupt pending for this pin */
|
||||
|
||||
mask = UINT32_C(1) << i;
|
||||
if ((status & mask) != 0)
|
||||
{
|
||||
/* Yes... perform the second level dispatch */
|
||||
|
||||
irq_dispatch(irq + i, regs);
|
||||
|
||||
/* Clear the bit in the status so that we might execute this loop
|
||||
* sooner.
|
||||
*/
|
||||
|
||||
status &= ~mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: gpio_interrupt
|
||||
*
|
||||
* Description:
|
||||
* GPIO interrupt handler.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Identifier of the interrupt request.
|
||||
* context - Context data from the ISR.
|
||||
* arg - Opaque pointer to the internal driver state structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) is returned on success; a negated errno value is returned
|
||||
* on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
static int gpio_interrupt(int irq, void *context, void *arg)
|
||||
{
|
||||
uint32_t status;
|
||||
|
||||
/* Read and clear the lower GPIO interrupt status */
|
||||
|
||||
status = getreg32(GPIO_STATUS_REG);
|
||||
putreg32(status, GPIO_STATUS_W1TC_REG);
|
||||
|
||||
/* Dispatch pending interrupts in the lower GPIO status register */
|
||||
|
||||
gpio_dispatch(ESP32S3_FIRST_GPIOIRQ, status, (uint32_t *)context);
|
||||
|
||||
/* Read and clear the upper GPIO interrupt status */
|
||||
|
||||
status = getreg32(GPIO_STATUS1_REG);
|
||||
putreg32(status, GPIO_STATUS1_W1TC_REG);
|
||||
|
||||
/* Dispatch pending interrupts in the lower GPIO status register */
|
||||
|
||||
gpio_dispatch(ESP32S3_FIRST_GPIOIRQ + 32, status, (uint32_t *)context);
|
||||
return OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -274,6 +366,137 @@ bool esp32s3_gpioread(int pin)
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpioirqinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize logic to support a second level of interrupt decoding for
|
||||
* GPIO pins.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
void esp32s3_gpioirqinitialize(void)
|
||||
{
|
||||
int cpu;
|
||||
|
||||
/* Setup the GPIO interrupt. */
|
||||
|
||||
cpu = up_cpu_index();
|
||||
|
||||
g_gpio_cpuint = esp32s3_setup_irq(cpu, ESP32S3_PERIPH_GPIO_INT_CPU, 1,
|
||||
ESP32S3_CPUINT_LEVEL);
|
||||
DEBUGASSERT(g_gpio_cpuint >= 0);
|
||||
|
||||
/* Attach and enable the interrupt handler */
|
||||
|
||||
DEBUGVERIFY(irq_attach(ESP32S3_IRQ_GPIO_INT_CPU, gpio_interrupt, NULL));
|
||||
up_enable_irq(ESP32S3_IRQ_GPIO_INT_CPU);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpioirqenable
|
||||
*
|
||||
* Description:
|
||||
* Enable the interrupt for the specified GPIO IRQ.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Identifier of the interrupt request.
|
||||
* intrtype - Interrupt type, select from gpio_intrtype_t.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
void esp32s3_gpioirqenable(int irq, gpio_intrtype_t intrtype)
|
||||
{
|
||||
uintptr_t regaddr;
|
||||
uint32_t regval;
|
||||
int pin;
|
||||
|
||||
DEBUGASSERT(irq >= ESP32S3_FIRST_GPIOIRQ && irq <= ESP32S3_LAST_GPIOIRQ);
|
||||
|
||||
/* Convert the IRQ number to a pin number */
|
||||
|
||||
pin = ESP32S3_IRQ2PIN(irq);
|
||||
|
||||
/* Disable the GPIO interrupt during the configuration. */
|
||||
|
||||
up_disable_irq(ESP32S3_IRQ_GPIO_INT_CPU);
|
||||
|
||||
/* Get the address of the GPIO PIN register for this pin */
|
||||
|
||||
regaddr = GPIO_REG(pin);
|
||||
regval = getreg32(regaddr);
|
||||
regval &= ~(GPIO_PIN0_INT_ENA_M | GPIO_PIN0_INT_TYPE_M);
|
||||
|
||||
/* Set the pin ENA field.
|
||||
* On ESP32-S3, CPU0 and CPU1 share the same interrupt enable bit.
|
||||
*/
|
||||
|
||||
regval |= GPIO_PIN0_INT_ENA_M;
|
||||
regval |= (uint32_t)intrtype << GPIO_PIN0_INT_TYPE_S;
|
||||
putreg32(regval, regaddr);
|
||||
|
||||
/* Configuration done. Re-enable the GPIO interrupt. */
|
||||
|
||||
up_enable_irq(ESP32S3_IRQ_GPIO_INT_CPU);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpioirqdisable
|
||||
*
|
||||
* Description:
|
||||
* Disable the interrupt for the specified GPIO IRQ.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Identifier of the interrupt request.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
void esp32s3_gpioirqdisable(int irq)
|
||||
{
|
||||
uintptr_t regaddr;
|
||||
uint32_t regval;
|
||||
int pin;
|
||||
|
||||
DEBUGASSERT(irq >= ESP32S3_FIRST_GPIOIRQ && irq <= ESP32S3_LAST_GPIOIRQ);
|
||||
|
||||
/* Convert the IRQ number to a pin number */
|
||||
|
||||
pin = ESP32S3_IRQ2PIN(irq);
|
||||
|
||||
/* Disable the GPIO interrupt during the configuration. */
|
||||
|
||||
up_disable_irq(ESP32S3_IRQ_GPIO_INT_CPU);
|
||||
|
||||
/* Reset the pin ENA and TYPE fields */
|
||||
|
||||
regaddr = GPIO_REG(pin);
|
||||
regval = getreg32(regaddr);
|
||||
regval &= ~(GPIO_PIN0_INT_ENA_M | GPIO_PIN0_INT_TYPE_M);
|
||||
putreg32(regval, regaddr);
|
||||
|
||||
/* Configuration done. Re-enable the GPIO interrupt. */
|
||||
|
||||
up_enable_irq(ESP32S3_IRQ_GPIO_INT_CPU);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpio_matrix_in
|
||||
*
|
||||
|
@ -93,15 +93,6 @@
|
||||
# define OUTPUT_FUNCTION_5 (OUTPUT_FUNCTION | FUNCTION_5)
|
||||
# define OUTPUT_FUNCTION_6 (OUTPUT_FUNCTION | FUNCTION_6)
|
||||
|
||||
/* Interrupt type used with esp32s3_gpioirqenable() */
|
||||
|
||||
#define DISABLED 0x00
|
||||
#define RISING 0x01
|
||||
#define FALLING 0x02
|
||||
#define CHANGE 0x03
|
||||
#define ONLOW 0x04
|
||||
#define ONHIGH 0x05
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
@ -111,7 +102,16 @@
|
||||
/* Must be big enough to hold the above encodings */
|
||||
|
||||
typedef uint16_t gpio_pinattr_t;
|
||||
typedef uint8_t gpio_intrtype_t;
|
||||
|
||||
typedef enum gpio_intrtype_e
|
||||
{
|
||||
GPIO_INTR_DISABLE = 0, /* Disable GPIO interrupt */
|
||||
GPIO_INTR_POSEDGE = 1, /* Rising edge */
|
||||
GPIO_INTR_NEGEDGE = 2, /* Falling edge */
|
||||
GPIO_INTR_ANYEDGE = 3, /* Both rising and falling edge */
|
||||
GPIO_INTR_LOW_LEVEL = 4, /* Input low level trigger */
|
||||
GPIO_INTR_HIGH_LEVEL = 5 /* Input high level trigger */
|
||||
} gpio_intrtype_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
@ -130,6 +130,27 @@ extern "C"
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpioirqinitialize
|
||||
*
|
||||
* Description:
|
||||
* Initialize logic to support a second level of interrupt decoding for
|
||||
* GPIO pins.
|
||||
*
|
||||
* Input Parameters:
|
||||
* None.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
void esp32s3_gpioirqinitialize(void);
|
||||
#else
|
||||
# define esp32s3_gpioirqinitialize()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_configgpio
|
||||
*
|
||||
@ -189,6 +210,47 @@ void esp32s3_gpiowrite(int pin, bool value);
|
||||
|
||||
bool esp32s3_gpioread(int pin);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpioirqenable
|
||||
*
|
||||
* Description:
|
||||
* Enable the interrupt for the specified GPIO IRQ.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Identifier of the interrupt request.
|
||||
* intrtype - Interrupt type, select from gpio_intrtype_t.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
void esp32s3_gpioirqenable(int irq, gpio_intrtype_t intrtype);
|
||||
#else
|
||||
# define esp32s3_gpioirqenable(irq,intrtype)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpioirqdisable
|
||||
*
|
||||
* Description:
|
||||
* Disable the interrupt for the specified GPIO IRQ.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Identifier of the interrupt request.
|
||||
*
|
||||
* Returned Value:
|
||||
* None.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ESP32S3_GPIO_IRQ
|
||||
void esp32s3_gpioirqdisable(int irq);
|
||||
#else
|
||||
# define esp32s3_gpioirqdisable(irq)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: esp32s3_gpio_matrix_in
|
||||
*
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "xtensa.h"
|
||||
|
||||
#include "esp32s3_gpio.h"
|
||||
#include "esp32s3_irq.h"
|
||||
#ifdef CONFIG_SMP
|
||||
#include "esp32s3_smp.h"
|
||||
@ -446,6 +447,10 @@ void up_irqinitialize(void)
|
||||
xtensa_attach_fromcpu1_interrupt();
|
||||
#endif
|
||||
|
||||
/* Initialize GPIO interrupt support */
|
||||
|
||||
esp32s3_gpioirqinitialize();
|
||||
|
||||
#ifndef CONFIG_SUPPRESS_INTERRUPTS
|
||||
/* And finally, enable interrupts. Also clears PS.EXCM */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user