diff --git a/arch/risc-v/include/esp32c3/irq.h b/arch/risc-v/include/esp32c3/irq.h index 2326fc9099..e200c73ffa 100644 --- a/arch/risc-v/include/esp32c3/irq.h +++ b/arch/risc-v/include/esp32c3/irq.h @@ -132,6 +132,7 @@ /* ecall is dispatched like normal interrupts. It occupies an IRQ number. */ #define ESP32C3_IRQ_ECALL_M 0 +#define RISCV_NIRQ_INTERRUPTS 1 /* Number of RISC-V dispatched interrupts. */ #define ESP32C3_IRQ_FIRSTPERIPH 1 /* First peripheral IRQ number */ /* Peripheral IRQs */ @@ -201,9 +202,24 @@ #define ESP32C3_NIRQ_PERIPH ESP32C3_NPERIPHERALS -/* Total number of IRQs: Number of peripheral IRQs + 1 for ecall. */ +/* 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. + */ -#define NR_IRQS (ESP32C3_NIRQ_PERIPH + 1) +#ifdef CONFIG_ESP32C3_GPIO_IRQ +# define ESP32C3_NIRQ_GPIO 22 +# define ESP32C3_FIRST_GPIOIRQ (RISCV_NIRQ_INTERRUPTS + ESP32C3_NIRQ_PERIPH) +# define ESP32C3_LAST_GPIOIRQ (ESP32C3_FIRST_GPIOIRQ + ESP32C3_NIRQ_GPIO - 1) +# define ESP32C3_PIN2IRQ(p) ((p) + ESP32C3_FIRST_GPIOIRQ) +# define ESP32C3_IRQ2PIN(i) ((i) - ESP32C3_FIRST_GPIOIRQ) +#else +# define ESP32C3_NIRQ_GPIO 0 +#endif + +/* Total number of IRQs: ecall + Number of peripheral IRQs + GPIOs IRQs. */ + +#define NR_IRQS (RISCV_NIRQ_INTERRUPTS + ESP32C3_NIRQ_PERIPH + ESP32C3_NIRQ_GPIO) /**************************************************************************** * Inline functions diff --git a/arch/risc-v/src/esp32c3/Kconfig b/arch/risc-v/src/esp32c3/Kconfig index d5a15a91d2..950fc374a2 100644 --- a/arch/risc-v/src/esp32c3/Kconfig +++ b/arch/risc-v/src/esp32c3/Kconfig @@ -104,6 +104,11 @@ config ESP32C3_CPU_FREQ_MHZ menu "ESP32-C3 Peripheral Support" +config ESP32C3_GPIO_IRQ + bool "GPIO pin interrupts" + ---help--- + Enable support for interrupting GPIO pins + config ESP32C3_UART0 bool "UART0" default y diff --git a/arch/risc-v/src/esp32c3/esp32c3_gpio.c b/arch/risc-v/src/esp32c3/esp32c3_gpio.c index 6b15822fe8..36e923dffc 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_gpio.c +++ b/arch/risc-v/src/esp32c3/esp32c3_gpio.c @@ -1,5 +1,5 @@ /**************************************************************************** - * arch/risc/src/esp32c3/esp32c3_gpio.c + * arch/risc-v/src/esp32c3/esp32c3_gpio.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -35,11 +35,75 @@ #include #include "riscv_arch.h" +#include "esp32c3_irq.h" #include "hardware/esp32c3_iomux.h" #include "hardware/esp32c3_gpio.h" #include "esp32c3_gpio.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +static int g_gpio_cpuint; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gpio_dispatch + * + * Description: + * Second level dispatch for GPIO interrupt handling. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +static void gpio_dispatch(int irq, uint32_t status, uint32_t *regs) +{ + int i; + int ndx = 0; + + /* Check set bits in the status register */ + + while ((i = __builtin_ffs(status))) + { + ndx += i; + irq_dispatch(irq + ndx - 1, regs); + status >>= i; + } +} +#endif + +/**************************************************************************** + * Name: gpio_interrupt + * + * Description: + * GPIO interrupt handler. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +static int gpio_interrupt(int irq, FAR void *context, FAR 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(ESP32C3_FIRST_GPIOIRQ, status, (uint32_t *)context); + + return OK; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -230,3 +294,118 @@ void esp32c3_gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, putreg32(regval, regaddr); } +/**************************************************************************** + * Name: esp32c3_gpioirqinitialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +void esp32c3_gpioirqinitialize(void) +{ + int ret; + + /* Allocate a level-sensitive, priority 1 CPU interrupt */ + + g_gpio_cpuint = esp32c3_request_irq(ESP32C3_PERIPH_GPIO, 1, + ESP32C3_INT_LEVEL); + DEBUGASSERT(g_gpio_cpuint > 0); + + up_disable_irq(g_gpio_cpuint); + + /* Attach and enable the IRQ */ + + ret = irq_attach(ESP32C3_IRQ_GPIO, gpio_interrupt, NULL); + if (ret == OK) + { + up_enable_irq(g_gpio_cpuint); + } + else + { + gpioerr("ERROR: GPIO interrupt not attached!\n"); + } + + gpioinfo("GPIO interrupt (%d) attached.\n", g_gpio_cpuint); +} +#endif + +/**************************************************************************** + * Name: esp32c3_gpioirqenable + * + * Description: + * Enable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +void esp32c3_gpioirqenable(int irq, gpio_intrtype_t intrtype) +{ + uintptr_t regaddr; + uint32_t regval; + int pin; + + DEBUGASSERT(irq >= ESP32C3_FIRST_GPIOIRQ && irq <= ESP32C3_LAST_GPIOIRQ); + + /* Convert the IRQ number to a pin number */ + + pin = ESP32C3_IRQ2PIN(irq); + + /* Disable the GPIO interrupt during the configuration. */ + + up_disable_irq(g_gpio_cpuint); + + /* Get the address of the GPIO PIN register for this pin */ + + regaddr = GPIO_REG(pin); + regval = getreg32(regaddr); + regval &= ~(GPIO_PIN_INT_ENA_M | GPIO_PIN_INT_TYPE_M); + + /* Set the pin ENA field. */ + + regval |= (1 << GPIO_PIN0_INT_ENA_S); + regval |= (intrtype << GPIO_PIN_INT_TYPE_S); + putreg32(regval, regaddr); + + /* Configuration done. Re-enable the GPIO interrupt. */ + + up_enable_irq(g_gpio_cpuint); +} +#endif + +/**************************************************************************** + * Name: esp32c3_gpioirqdisable + * + * Description: + * Disable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +void esp32c3_gpioirqdisable(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + int pin; + + DEBUGASSERT(irq >= ESP32C3_FIRST_GPIOIRQ && irq <= ESP32C3_LAST_GPIOIRQ); + + /* Convert the IRQ number to a pin number */ + + pin = ESP32C3_IRQ2PIN(irq); + + /* Get the address of the GPIO PIN register for this pin */ + + up_disable_irq(g_gpio_cpuint); + + regaddr = GPIO_REG(pin); + regval = getreg32(regaddr); + regval &= ~(GPIO_PIN_INT_ENA_M | GPIO_PIN_INT_TYPE_M); + putreg32(regval, regaddr); + + up_enable_irq(g_gpio_cpuint); +} +#endif + diff --git a/arch/risc-v/src/esp32c3/esp32c3_gpio.h b/arch/risc-v/src/esp32c3/esp32c3_gpio.h index 0a4423a342..a7a2ced74f 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_gpio.h +++ b/arch/risc-v/src/esp32c3/esp32c3_gpio.h @@ -76,6 +76,15 @@ # define OUTPUT_FUNCTION_3 (OUTPUT_FUNCTION | FUNCTION_3) # define OUTPUT_FUNCTION_4 (OUTPUT_FUNCTION | FUNCTION_4) +/* Interrupt type used with esp32c3_gpioirqenable() */ + +#define DISABLED 0x00 +#define RISING 0x01 +#define FALLING 0x02 +#define CHANGE 0x03 +#define ONLOW 0x04 +#define ONHIGH 0x05 + /**************************************************************************** * Public Types ****************************************************************************/ @@ -85,6 +94,7 @@ /* Must be big enough to hold the above encodings */ typedef uint16_t gpio_pinattr_t; +typedef uint8_t gpio_intrtype_t; /**************************************************************************** * Public Data @@ -159,6 +169,50 @@ void esp32c3_gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv); void esp32c3_gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv); +/**************************************************************************** + * Name: esp32c3_gpioirqinitialize + * + * Description: + * Initialize logic to support a second level of interrupt decoding for + * GPIO pins. + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +void esp32c3_gpioirqinitialize(void); +#else +# define esp32c3_gpioirqinitialize() +#endif + + +/**************************************************************************** + * Name: esp32c3_gpioirqenable + * + * Description: + * Enable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +void esp32c3_gpioirqenable(int irq, gpio_intrtype_t intrtype); +#else +# define esp32c3_gpioirqenable(irq,intrtype) +#endif + +/**************************************************************************** + * Name: esp32c3_gpioirqdisable + * + * Description: + * Disable the interrupt for specified GPIO IRQ + * + ****************************************************************************/ + +#ifdef CONFIG_ESP32C3_GPIO_IRQ +void esp32c3_gpioirqdisable(int irq); +#else +# define esp32c3_gpioirqdisable(irq) +#endif + #ifdef __cplusplus } #endif diff --git a/arch/risc-v/src/esp32c3/esp32c3_irq.c b/arch/risc-v/src/esp32c3/esp32c3_irq.c index 2ebc5e1b82..f57ed77c35 100644 --- a/arch/risc-v/src/esp32c3/esp32c3_irq.c +++ b/arch/risc-v/src/esp32c3/esp32c3_irq.c @@ -40,6 +40,7 @@ #include "esp32c3.h" #include "esp32c3_attr.h" +#include "esp32c3_gpio.h" #include "esp32c3_irq.h" @@ -96,6 +97,12 @@ void up_irqinitialize(void) irq_attach(ESP32C3_IRQ_ECALL_M, up_swint, NULL); +#ifdef CONFIG_ESP32C3_GPIO_IRQ + /* Initialize GPIO interrupt support */ + + esp32c3_gpioirqinitialize(); +#endif + #ifndef CONFIG_SUPPRESS_INTERRUPTS /* And finally, enable interrupts */ diff --git a/arch/risc-v/src/esp32c3/hardware/esp32c3_gpio.h b/arch/risc-v/src/esp32c3/hardware/esp32c3_gpio.h index 662282c779..e4391fc572 100644 --- a/arch/risc-v/src/esp32c3/hardware/esp32c3_gpio.h +++ b/arch/risc-v/src/esp32c3/hardware/esp32c3_gpio.h @@ -33,6 +33,26 @@ #define GPIO_REG(io_num) (GPIO_PIN0_REG + ((io_num) * 0x4)) +#define GPIO_PIN_INT_ENA 0x0000001F +#define GPIO_PIN_INT_ENA_M ((GPIO_PIN_INT_ENA_V)<<(GPIO_PIN_INT_ENA_S)) +#define GPIO_PIN_INT_ENA_V 0x0000001F +#define GPIO_PIN_INT_ENA_S 13 + +#define GPIO_PIN_CONFIG 0x00000003 +#define GPIO_PIN_CONFIG_M ((GPIO_PIN_CONFIG_V)<<(GPIO_PIN_CONFIG_S)) +#define GPIO_PIN_CONFIG_V 0x00000003 +#define GPIO_PIN_CONFIG_S 11 + +#define GPIO_PIN_WAKEUP_ENABLE (BIT(10)) +#define GPIO_PIN_WAKEUP_ENABLE_M (BIT(10)) +#define GPIO_PIN_WAKEUP_ENABLE_V 0x1 +#define GPIO_PIN_WAKEUP_ENABLE_S 10 + +#define GPIO_PIN_INT_TYPE 0x00000007 +#define GPIO_PIN_INT_TYPE_M ((GPIO_PIN_INT_TYPE_V)<<(GPIO_PIN_INT_TYPE_S)) +#define GPIO_PIN_INT_TYPE_V 0x00000007 +#define GPIO_PIN_INT_TYPE_S 7 + #define GPIO_PIN_CONFIG_MSB 12 #define GPIO_PIN_CONFIG_LSB 11 #define GPIO_PIN_CONFIG_MASK 0x00001800 @@ -53,13 +73,20 @@ #define GPIO_PIN_INT_TYPE_GET(x) (((x) & GPIO_PIN_INT_TYPE_MASK) >> GPIO_PIN_INT_TYPE_LSB) #define GPIO_PIN_INT_TYPE_SET(x) (((x) << GPIO_PIN_INT_TYPE_LSB) & GPIO_PIN_INT_TYPE_MASK) -#define GPIO_PAD_DRIVER_ENABLE 1 -#define GPIO_PAD_DRIVER_DISABLE (~GPIO_PAD_DRIVER_ENABLE) -#define GPIO_PIN_PAD_DRIVER_MSB 2 -#define GPIO_PIN_PAD_DRIVER_LSB 2 -#define GPIO_PIN_PAD_DRIVER_MASK 0x00000004 -#define GPIO_PIN_PAD_DRIVER_GET(x) (((x) & GPIO_PIN_PAD_DRIVER_MASK) >> GPIO_PIN_PAD_DRIVER_LSB) -#define GPIO_PIN_PAD_DRIVER_SET(x) (((x) << GPIO_PIN_PAD_DRIVER_LSB) & GPIO_PIN_PAD_DRIVER_MASK) +#define GPIO_PIN_SYNC1_BYPASS 0x00000003 +#define GPIO_PIN_SYNC1_BYPASS_M ((GPIO_PIN0_SYNC1_BYPASS_V)<<(GPIO_PIN0_SYNC1_BYPASS_S)) +#define GPIO_PIN_SYNC1_BYPASS_V 0x3 +#define GPIO_PIN_SYNC1_BYPASS_S 3 + +#define GPIO_PIN_PAD_DRIVER (BIT(2)) +#define GPIO_PIN_PAD_DRIVER_M (BIT(2)) +#define GPIO_PIN_PAD_DRIVER_V 0x1 +#define GPIO_PIN_PAD_DRIVER_S 2 + +#define GPIO_PIN_SYNC2_BYPASS 0x00000003 +#define GPIO_PIN_SYNC2_BYPASS_M ((GPIO_PIN0_SYNC2_BYPASS_V)<<(GPIO_PIN0_SYNC2_BYPASS_S)) +#define GPIO_PIN_SYNC2_BYPASS_V 0x3 +#define GPIO_PIN_SYNC2_BYPASS_S 0 #define GPIO_BT_SELECT_REG (DR_REG_GPIO_BASE + 0x0) diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/README.txt b/boards/risc-v/esp32c3/esp32c3-devkit/README.txt index 23dc3cb5ca..b847f7ad7d 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/README.txt +++ b/boards/risc-v/esp32c3/esp32c3-devkit/README.txt @@ -80,7 +80,9 @@ Configurations gpio ____ - This is a test for the GPIO driver. It uses GPIO1 and GPIO2 as outputs. + This is a test for the GPIO driver. It uses GPIO1 and GPIO2 as outputs and + GPIO9 as an interrupt pin. + At the nsh, we can turn the outputs on and off with the following: nsh> gpio -o 1 /dev/gpout0 nsh> gpio -o 1 /dev/gpout1 @@ -88,6 +90,12 @@ Configurations nsh> gpio -o 0 /dev/gpout0 nsh> gpio -o 0 /dev/gpout1 + We can use the interrupt pin to send a signal when the interrupt fires: + nsh> gpio -w 14 /dev/gpint2 + + The pin is configured as a rising edge interrupt, so after issuing the + above command, connect it to 3.3V. + Building and flashing ===================== diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/configs/gpio/defconfig b/boards/risc-v/esp32c3/esp32c3-devkit/configs/gpio/defconfig index a28b2faf3a..feca198737 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/configs/gpio/defconfig +++ b/boards/risc-v/esp32c3/esp32c3-devkit/configs/gpio/defconfig @@ -17,18 +17,14 @@ CONFIG_ARCH_CHIP_ESP32C3WROOM02=y CONFIG_ARCH_INTERRUPTSTACK=1536 CONFIG_ARCH_RISCV=y CONFIG_ARCH_STACKDUMP=y -CONFIG_BINFMT_DISABLE=y CONFIG_BOARD_LOOPSPERMSEC=15000 CONFIG_BUILTIN=y CONFIG_DEV_GPIO=y CONFIG_DEV_ZERO=y -CONFIG_DISABLE_MQUEUE=y +CONFIG_ESP32C3_GPIO_IRQ=y CONFIG_EXAMPLES_GPIO=y -CONFIG_EXAMPLES_HELLO=y -CONFIG_EXAMPLES_HELLO_STACKSIZE=1024 CONFIG_FS_PROCFS=y CONFIG_IDLETHREAD_STACKSIZE=2048 -CONFIG_INPUT=y CONFIG_INTELHEX_BINARY=y CONFIG_LIBC_PERROR_STDOUT=y CONFIG_LIBC_STRERROR=y @@ -36,30 +32,18 @@ CONFIG_MAX_TASKS=8 CONFIG_NFILE_DESCRIPTORS=6 CONFIG_NSH_ARCHINIT=y CONFIG_NSH_BUILTIN_APPS=y -CONFIG_NSH_DISABLE_CD=y -CONFIG_NSH_DISABLE_CP=y -CONFIG_NSH_DISABLE_IFUPDOWN=y -CONFIG_NSH_DISABLE_MKDIR=y -CONFIG_NSH_DISABLE_RM=y -CONFIG_NSH_DISABLE_RMDIR=y -CONFIG_NSH_DISABLE_UMOUNT=y -CONFIG_NSH_FILEIOSIZE=64 +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y CONFIG_NSH_STRERROR=y CONFIG_PREALLOC_TIMERS=0 -CONFIG_PTHREAD_STACK_DEFAULT=1536 -CONFIG_RAM_SIZE=16384 -CONFIG_RAM_START=0x80000000 CONFIG_RAW_BINARY=y CONFIG_RR_INTERVAL=200 CONFIG_SCHED_WAITPID=y CONFIG_START_DAY=29 CONFIG_START_MONTH=11 CONFIG_START_YEAR=2019 -CONFIG_STDIO_DISABLE_BUFFERING=y CONFIG_SYSTEM_NSH=y CONFIG_TASK_NAME_SIZE=12 CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=1536 -CONFIG_TESTING_GETPRIME=y CONFIG_UART0_SERIAL_CONSOLE=y -CONFIG_USERMAIN_STACKSIZE=1536 CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/include/board.h b/boards/risc-v/esp32c3/esp32c3-devkit/include/board.h index 1d0432f730..07d6e4c5f9 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/include/board.h +++ b/boards/risc-v/esp32c3/esp32c3-devkit/include/board.h @@ -32,6 +32,7 @@ /* GPIO pins used by the GPIO Subsystem */ #define BOARD_NGPIOOUT 2 /* Amount of GPIO Output pins */ +#define BOARD_NGPIOINT 1 /* Amount of GPIO Input w/ Interruption pins */ #endif /* __BOARDS_RISCV_ESP32C3_ESP32C3_DEVKIT_INCLUDE_BOARD_H */ diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_gpio.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_gpio.c index 3844e9ba36..c4095bb508 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_gpio.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_gpio.c @@ -30,6 +30,9 @@ #include #include +#include +#include + #include #include @@ -38,6 +41,8 @@ #include "esp32c3_gpio.h" #include "hardware/esp32c3_gpio_sigmap.h" +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -47,7 +52,15 @@ #define GPIO_OUT1 1 #define GPIO_OUT2 2 -#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) +#if !defined(CONFIG_ESP32C3_GPIO_IRQ) && BOARD_NGPIOINT > 0 +# error "NGPIOINT is > 0 and GPIO interrupts aren't enabled" +#endif + +/* Interrupt pins. GPIO9 is used as an example, any other inputs could be + * used. + */ + +#define GPIO_IRQPIN 9 /**************************************************************************** * Private Types @@ -59,6 +72,12 @@ struct esp32c3gpio_dev_s uint8_t id; }; +struct esp32c3gpint_dev_s +{ + struct esp32c3gpio_dev_s esp32c3gpio; + pin_interrupt_t callback; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -68,6 +87,13 @@ static int gpout_read(FAR struct gpio_dev_s *dev, FAR bool *value); static int gpout_write(FAR struct gpio_dev_s *dev, bool value); #endif +#if BOARD_NGPIOINT > 0 +static int gpint_read(FAR struct gpio_dev_s *dev, FAR bool *value); +static int gpint_attach(FAR struct gpio_dev_s *dev, + pin_interrupt_t callback); +static int gpint_enable(FAR struct gpio_dev_s *dev, bool enable); +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -91,6 +117,25 @@ static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] = static struct esp32c3gpio_dev_s g_gpout[BOARD_NGPIOOUT]; #endif +#if BOARD_NGPIOINT > 0 +static const struct gpio_operations_s gpint_ops = +{ + .go_read = gpint_read, + .go_write = NULL, + .go_attach = gpint_attach, + .go_enable = gpint_enable, +}; + +/* This array maps the GPIO pins used as INTERRUPT INPUTS */ + +static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] = +{ + GPIO_IRQPIN, +}; + +static struct esp32c3gpint_dev_s g_gpint[BOARD_NGPIOINT]; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -131,6 +176,103 @@ static int gpout_write(FAR struct gpio_dev_s *dev, bool value) } #endif +/**************************************************************************** + * Name: esp32c3gpio_interrupt + ****************************************************************************/ + +#if BOARD_NGPIOINT > 0 +static int esp32c3gpio_interrupt(int irq, void *context, void *arg) +{ + FAR struct esp32c3gpint_dev_s *esp32c3gpint = + (FAR struct esp32c3gpint_dev_s *)arg; + + DEBUGASSERT(esp32c3gpint != NULL && esp32c3gpint->callback != NULL); + gpioinfo("Interrupt! callback=%p\n", esp32c3gpint->callback); + + esp32c3gpint->callback(&esp32c3gpint->esp32c3gpio.gpio, + esp32c3gpint->esp32c3gpio.id); + return OK; +} + +/**************************************************************************** + * Name: gpint_read + ****************************************************************************/ + +static int gpint_read(FAR struct gpio_dev_s *dev, FAR bool *value) +{ + FAR struct esp32c3gpint_dev_s *esp32c3gpint = + (FAR struct esp32c3gpint_dev_s *)dev; + + DEBUGASSERT(esp32c3gpint != NULL && value != NULL); + DEBUGASSERT(esp32c3gpint->esp32c3gpio.id < BOARD_NGPIOINT); + gpioinfo("Reading int pin...\n"); + + *value = esp32c3_gpioread(g_gpiointinputs[esp32c3gpint->esp32c3gpio.id]); + return OK; +} + +/**************************************************************************** + * Name: gpint_attach + ****************************************************************************/ + +static int gpint_attach(FAR struct gpio_dev_s *dev, + pin_interrupt_t callback) +{ + FAR struct esp32c3gpint_dev_s *esp32c3gpint = + (FAR struct esp32c3gpint_dev_s *)dev; + int irq = ESP32C3_PIN2IRQ(g_gpiointinputs[esp32c3gpint->esp32c3gpio.id]); + int ret; + + gpioinfo("Attaching the callback\n"); + + /* Make sure the interrupt is disabled */ + + esp32c3_gpioirqdisable(irq); + ret = irq_attach(irq, + esp32c3gpio_interrupt, + &g_gpint[esp32c3gpint->esp32c3gpio.id]); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: gpint_attach() failed: %d\n", ret); + return ret; + } + + gpioinfo("Attach %p\n", callback); + esp32c3gpint->callback = callback; + return OK; +} + +/**************************************************************************** + * Name: gpint_enable + ****************************************************************************/ + +static int gpint_enable(FAR struct gpio_dev_s *dev, bool enable) +{ + FAR struct esp32c3gpint_dev_s *esp32c3gpint = + (FAR struct esp32c3gpint_dev_s *)dev; + int irq = ESP32C3_PIN2IRQ(g_gpiointinputs[esp32c3gpint->esp32c3gpio.id]); + + if (enable) + { + if (esp32c3gpint->callback != NULL) + { + gpioinfo("Enabling the interrupt\n"); + + /* Configure the interrupt for rising edge */ + + esp32c3_gpioirqenable(irq, RISING); + } + } + else + { + gpioinfo("Disable the interrupt\n"); + esp32c3_gpioirqdisable(irq); + } + + return OK; +} +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -164,6 +306,24 @@ int esp32c3_gpio_init(void) } #endif +#if BOARD_NGPIOINT > 0 + for (i = 0; i < BOARD_NGPIOINT; i++) + { + /* Setup and register the GPIO pin */ + + g_gpint[i].esp32c3gpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN; + g_gpint[i].esp32c3gpio.gpio.gp_ops = &gpint_ops; + g_gpint[i].esp32c3gpio.id = i; + gpio_pin_register(&g_gpint[i].esp32c3gpio.gpio, pincount); + + /* Configure the pins that will be used as interrupt input */ + + esp32c3_configgpio(g_gpiointinputs[i], INPUT_FUNCTION_1 | PULLDOWN); + + pincount++; + } +#endif + return OK; } #endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */