esp32c3: Add GPIO IRQ support.
The GPIO example was also extended to include testing an interrupt pin. Co-authored-by: Abdelatif Guettouche <abdelatif.guettouche@espressif.com> Co-authored-by: Alan Carvalho <alan.carvalho@espressif.com>
This commit is contained in:
parent
4a42998f36
commit
10822799fb
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 <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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
=====================
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
****************************************************************************/
|
||||
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user