This is an automated email from the ASF dual-hosted git repository.

protobits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 10822799fbc28d08806d76f39d264b2d0241b518
Author: Abdelatif Guettouche <abdelatif.guettou...@espressif.com>
AuthorDate: Thu Feb 18 13:26:28 2021 +0100

    esp32c3: Add GPIO IRQ support.
    
    The GPIO example was also extended to include testing an interrupt pin.
    
    Co-authored-by: Abdelatif Guettouche <abdelatif.guettou...@espressif.com>
    Co-authored-by: Alan Carvalho <alan.carva...@espressif.com>
---
 arch/risc-v/include/esp32c3/irq.h                  |  20 ++-
 arch/risc-v/src/esp32c3/Kconfig                    |   5 +
 arch/risc-v/src/esp32c3/esp32c3_gpio.c             | 181 ++++++++++++++++++++-
 arch/risc-v/src/esp32c3/esp32c3_gpio.h             |  54 ++++++
 arch/risc-v/src/esp32c3/esp32c3_irq.c              |   7 +
 arch/risc-v/src/esp32c3/hardware/esp32c3_gpio.h    |  41 ++++-
 boards/risc-v/esp32c3/esp32c3-devkit/README.txt    |  10 +-
 .../esp32c3/esp32c3-devkit/configs/gpio/defconfig  |  22 +--
 .../risc-v/esp32c3/esp32c3-devkit/include/board.h  |   1 +
 .../esp32c3/esp32c3-devkit/src/esp32c3_gpio.c      | 162 +++++++++++++++++-
 10 files changed, 472 insertions(+), 31 deletions(-)

diff --git a/arch/risc-v/include/esp32c3/irq.h 
b/arch/risc-v/include/esp32c3/irq.h
index 2326fc9..e200c73 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.
+ */
+
+#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                         (ESP32C3_NIRQ_PERIPH + 1)
+#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 d5a15a9..950fc37 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 6b15822..36e923d 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,12 +35,76 @@
 #include <arch/esp32c3/chip.h>
 
 #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 0a4423a..a7a2ced 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 2ebc5e1..f57ed77 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 662282c..e4391fc 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 23dc3cb..b847f7a 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 a28b2fa..feca198 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 1d0432f..07d6e4c 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 3844e9b..c4095bb 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 <assert.h>
 #include <debug.h>
 
+#include <nuttx/irq.h>
+#include <arch/irq.h>
+
 #include <nuttx/ioexpander/gpio.h>
 
 #include <arch/board/board.h>
@@ -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
  ****************************************************************************/
@@ -132,6 +177,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 */

Reply via email to