arch/risc-v/espressif: Add full GPIO support

Full GPIO support using Espressif's HAL
This commit is contained in:
Lucas Saavedra Vaz 2023-06-23 14:44:32 -03:00 committed by Xiang Xiao
parent efd1b838e6
commit 8aeba210e4
10 changed files with 406 additions and 8 deletions

View file

@ -1 +1,2 @@
/gpio_sig_map.h
/irq.h

View file

@ -196,6 +196,14 @@ config ESPRESSIF_ESPTOOLPY_NO_STUB
It is only required to be disabled in certain scenarios when either
Secure Boot V2 or Flash Encryption is enabled.
config ESPRESSIF_HAL_ASSERTIONS
bool "Enable HAL assertions"
depends on DEBUG_ASSERTIONS
default y
---help---
Enable the assertions implemented in the HAL. Otherwise, the assertions
are replaced by empty macros.
menu "Peripheral Support"
config ESPRESSIF_UART
@ -216,6 +224,12 @@ config ESPRESSIF_UART1
select UART1_SERIALDRIVER
select ARCH_HAVE_SERIAL_TERMIOS
config ESPRESSIF_GPIO_IRQ
bool "GPIO pin interrupts"
default n
---help---
Enable support for interrupting GPIO pins
config ESPRESSIF_HR_TIMER
bool
default y if RTC_DRIVER

View file

@ -39,33 +39,33 @@ CHIP_CSRCS += esp_lowputc.c esp_serial.c
CHIP_CSRCS += esp_systemreset.c
ifeq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += esp_tickless.c
CHIP_CSRCS += esp_tickless.c
else
CHIP_CSRCS += esp_timerisr.c
CHIP_CSRCS += esp_timerisr.c
endif
ifeq ($(CONFIG_WATCHDOG),y)
CHIP_CSRCS += esp_wdt.c
CHIP_CSRCS += esp_wdt.c
endif
ifneq ($(CONFIG_DEV_RANDOM)$(CONFIG_DEV_URANDOM_ARCH),)
CHIP_CSRCS += esp_random.c
CHIP_CSRCS += esp_random.c
endif
ifeq ($(CONFIG_TIMER),y)
CHIP_CSRCS += esp_timer.c
CHIP_CSRCS += esp_timer.c
endif
ifeq ($(CONFIG_ONESHOT),y)
CHIP_CSRCS += esp_oneshot.c
CHIP_CSRCS += esp_oneshot.c
endif
ifeq ($(CONFIG_RTC),y)
CHIP_CSRCS += esp_rtc.c
CHIP_CSRCS += esp_rtc.c
endif
ifeq ($(CONFIG_ESPRESSIF_HR_TIMER),y)
CHIP_CSRCS += esp_hr_timer.c
CHIP_CSRCS += esp_hr_timer.c
endif
#############################################################################
@ -99,8 +99,10 @@ CHIP_SERIES = $(patsubst "%",%,$(CONFIG_ESPRESSIF_CHIP_SERIES))
include chip/hal_${CHIP_SERIES}.mk
context:: chip/$(ESP_HAL_3RDPARTY_REPO)
$(call COPYFILE,chip/$(ESP_HAL_3RDPARTY_REPO)/components/soc/$(CHIP_SERIES)/include/soc/gpio_sig_map.h,../include/chip/)
$(call COPYFILE,chip/$(ESP_HAL_3RDPARTY_REPO)/nuttx/$(CHIP_SERIES)/include/irq.h,../include/chip/)
distclean::
$(call DELFILE,../include/chip/gpio_sig_map.h)
$(call DELFILE,../include/chip/irq.h)
$(call DELDIR,chip/$(ESP_HAL_3RDPARTY_REPO))

View file

@ -22,20 +22,33 @@
* Included Files
****************************************************************************/
/* Config */
#include <nuttx/config.h>
/* Libc */
#include <assert.h>
#include <debug.h>
#include <stdint.h>
#include <sys/types.h>
/* NuttX */
#include <arch/irq.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
/* Arch */
#include "riscv_internal.h"
#include "esp_gpio.h"
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
# include "esp_irq.h"
#endif
/* HAL */
#include "esp_rom_gpio.h"
#include "hal/gpio_hal.h"
@ -49,6 +62,89 @@ static gpio_hal_context_t g_gpio_hal =
.dev = GPIO_HAL_GET_HW(GPIO_PORT_0)
};
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
static int g_gpio_cpuint;
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* 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_ESPRESSIF_GPIO_IRQ
static void gpio_dispatch(int irq, uint32_t status, uint32_t *regs)
{
int i;
/* Check set bits in the status register */
while ((i = __builtin_ffs(status)) > 0)
{
irq_dispatch(irq + i - 1, regs);
status >>= i;
}
}
#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_ESPRESSIF_GPIO_IRQ
static int gpio_interrupt(int irq, void *context, void *arg)
{
int i;
uint32_t status;
uint32_t intr_bitmask;
int cpu = up_cpu_index();
/* Read the lower GPIO interrupt status */
gpio_hal_get_intr_status(&g_gpio_hal, cpu, &status);
intr_bitmask = status;
while ((i = __builtin_ffs(intr_bitmask)) > 0)
{
gpio_hal_clear_intr_status_bit(&g_gpio_hal, (i - 1));
intr_bitmask >>= i;
}
/* Dispatch pending interrupts in the lower GPIO status register */
gpio_dispatch(ESP_FIRST_GPIOIRQ, status, (uint32_t *)context);
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -203,3 +299,163 @@ void esp_gpio_matrix_out(uint32_t pin, uint32_t signal_idx, bool out_inv,
esp_rom_gpio_connect_out_signal(pin, signal_idx, out_inv, oen_inv);
}
/****************************************************************************
* Name: esp_gpiowrite
*
* Description:
* Write one or zero to the selected GPIO pin
*
* Input Parameters:
* pin - GPIO pin to be modified.
* value - The value to be written (0 or 1).
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_gpiowrite(int pin, bool value)
{
DEBUGASSERT(pin >= 0 && pin <= SOC_GPIO_PIN_COUNT);
gpio_hal_set_level(&g_gpio_hal, pin, value);
}
/****************************************************************************
* Name: esp_gpioread
*
* Description:
* Read one or zero from the selected GPIO pin
*
* Input Parameters:
* pin - GPIO pin to be read.
*
* Returned Value:
* The boolean representation of the input value (true/false).
*
****************************************************************************/
bool esp_gpioread(int pin)
{
DEBUGASSERT(pin >= 0 && pin <= SOC_GPIO_PIN_COUNT);
return gpio_hal_get_level(&g_gpio_hal, pin) != 0;
}
/****************************************************************************
* Name: esp_gpioirqinitialize
*
* Description:
* Initialize logic to support a second level of interrupt decoding for
* GPIO pins.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
void esp_gpioirqinitialize(void)
{
/* Setup the GPIO interrupt. */
g_gpio_cpuint = esp_setup_irq(GPIO_INTR_SOURCE,
ESP_IRQ_PRIORITY_DEFAULT,
ESP_IRQ_TRIGGER_LEVEL);
DEBUGASSERT(g_gpio_cpuint >= 0);
/* Attach and enable the interrupt handler */
DEBUGVERIFY(irq_attach(ESP_IRQ_GPIO, gpio_interrupt, NULL));
up_enable_irq(ESP_IRQ_GPIO);
}
#endif
/****************************************************************************
* Name: esp_gpioirqenable
*
* Description:
* Enable the interrupt for specified GPIO IRQ
*
* Input Parameters:
* irq - GPIO IRQ number to be enabled.
* intrtype - Interrupt type to be enabled.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
void esp_gpioirqenable(int irq, gpio_intrtype_t intrtype)
{
uintptr_t regaddr;
uint32_t regval;
int pin;
int cpu;
DEBUGASSERT(irq >= ESP_FIRST_GPIOIRQ && irq <= ESP_LAST_GPIOIRQ);
/* Convert the IRQ number to a pin number */
pin = ESP_IRQ2PIN(irq);
/* Disable the GPIO interrupt during the configuration. */
up_disable_irq(ESP_IRQ_GPIO);
/* Enable interrupt for this pin on the current core */
cpu = up_cpu_index();
gpio_hal_set_intr_type(&g_gpio_hal, pin, intrtype);
gpio_hal_intr_enable_on_core(&g_gpio_hal, pin, cpu);
/* Configuration done. Re-enable the GPIO interrupt. */
up_enable_irq(ESP_IRQ_GPIO);
}
#endif
/****************************************************************************
* Name: esp_gpioirqdisable
*
* Description:
* Disable the interrupt for specified GPIO IRQ
*
* Input Parameters:
* irq - GPIO IRQ number to be disabled.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
void esp_gpioirqdisable(int irq)
{
uintptr_t regaddr;
uint32_t regval;
int pin;
DEBUGASSERT(irq >= ESP_FIRST_GPIOIRQ && irq <= ESP_LAST_GPIOIRQ);
/* Convert the IRQ number to a pin number */
pin = ESP_IRQ2PIN(irq);
/* Disable the GPIO interrupt during the configuration. */
up_disable_irq(ESP_IRQ_GPIO);
/* Disable the interrupt for this pin */
gpio_hal_intr_disable(&g_gpio_hal, pin);
/* Configuration done. Re-enable the GPIO interrupt. */
up_enable_irq(ESP_IRQ_GPIO);
}
#endif

View file

@ -89,6 +89,15 @@
# define OUTPUT_FUNCTION_5 (OUTPUT_FUNCTION | FUNCTION_5)
# define OUTPUT_FUNCTION_6 (OUTPUT_FUNCTION | FUNCTION_6)
/* Interrupt type used with esp_gpioirqenable() */
#define DISABLED 0x00
#define RISING 0x01
#define FALLING 0x02
#define CHANGE 0x03
#define ONLOW 0x04
#define ONHIGH 0x05
/****************************************************************************
* Public Types
****************************************************************************/
@ -98,6 +107,7 @@
/* Must be big enough to hold the above encodings */
typedef uint16_t gpio_pinattr_t;
typedef uint8_t gpio_intrtype_t;
/****************************************************************************
* Public Data
@ -187,6 +197,101 @@ void esp_gpio_matrix_in(uint32_t pin, uint32_t signal_idx, bool inv);
void esp_gpio_matrix_out(uint32_t pin, uint32_t signal_idx, bool out_inv,
bool oen_inv);
/****************************************************************************
* Name: esp_gpiowrite
*
* Description:
* Write one or zero to the selected GPIO pin
*
* Input Parameters:
* pin - GPIO pin to be modified.
* value - The value to be written (0 or 1).
*
* Returned Value:
* None.
*
****************************************************************************/
void esp_gpiowrite(int pin, bool value);
/****************************************************************************
* Name: esp_gpioread
*
* Description:
* Read one or zero from the selected GPIO pin
*
* Input Parameters:
* pin - GPIO pin to be read.
*
* Returned Value:
* The boolean representation of the input value (true/false).
*
****************************************************************************/
bool esp_gpioread(int pin);
/****************************************************************************
* Name: esp_gpioirqinitialize
*
* Description:
* Initialize logic to support a second level of interrupt decoding for
* GPIO pins.
*
* Input Parameters:
* None.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
void esp_gpioirqinitialize(void);
#else
# define esp_gpioirqinitialize()
#endif
/****************************************************************************
* Name: esp_gpioirqenable
*
* Description:
* Enable the interrupt for specified GPIO IRQ
*
* Input Parameters:
* irq - GPIO IRQ number to be enabled.
* intrtype - Interrupt type to be enabled.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
void esp_gpioirqenable(int irq, gpio_intrtype_t intrtype);
#else
# define esp_gpioirqenable(irq,intrtype)
#endif
/****************************************************************************
* Name: esp_gpioirqdisable
*
* Description:
* Disable the interrupt for specified GPIO IRQ
*
* Input Parameters:
* irq - GPIO IRQ number to be disabled.
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
void esp_gpioirqdisable(int irq);
#else
# define esp_gpioirqdisable(irq)
#endif
#ifdef __cplusplus
}
#endif

View file

@ -35,6 +35,7 @@
#include "riscv_internal.h"
#include "esp_gpio.h"
#include "esp_irq.h"
#include "esp_attr.h"
@ -290,6 +291,12 @@ void up_irqinitialize(void)
esp_cpuint_initialize();
/* Initialize GPIO interrupt support */
#ifdef CONFIG_ESPRESSIF_GPIO_IRQ
esp_gpioirqinitialize();
#endif
/* Attach the common interrupt handler */
riscv_exception_attach();
@ -322,6 +329,8 @@ void up_enable_irq(int irq)
irqinfo("irq=%d | cpuint=%d \n", irq, cpuint);
/* Check if IRQ is initialized */
DEBUGASSERT(cpuint >= 0 && cpuint < ESP_NCPUINTS);
irqstate_t irqstate = enter_critical_section();
@ -352,6 +361,8 @@ void up_disable_irq(int irq)
irqinfo("irq=%d | cpuint=%d \n", irq, cpuint);
/* Check if IRQ is initialized */
DEBUGASSERT(cpuint >= 0 && cpuint < ESP_NCPUINTS);
irqstate_t irqstate = enter_critical_section();

View file

@ -84,6 +84,7 @@ CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/esp_system/port/soc/$(CHI
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/esp_system/port/soc/$(CHIP_SERIES)/system_internal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/brownout_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/efuse_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/gpio_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/systimer_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/timer_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/timer_hal_iram.c

View file

@ -89,6 +89,7 @@ CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/esp_system/port/soc/$(CHI
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/esp_system/port/soc/$(CHIP_SERIES)/system_internal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/brownout_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/efuse_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/gpio_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/timer_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/timer_hal_iram.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/uart_hal.c

View file

@ -89,6 +89,7 @@ CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/esp_system/port/soc/$(CHI
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/brownout_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/cache_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/efuse_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/gpio_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/timer_hal.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/timer_hal_iram.c
CHIP_CSRCS += chip/$(ESP_HAL_3RDPARTY_REPO)/components/hal/uart_hal.c

View file

@ -380,6 +380,8 @@ config ARCH_BOARD_ESP32C3_DEVKIT_RUST1
config ARCH_BOARD_ESP32C3_GENERIC
bool "Espressif ESP32-C3 Generic DevKit"
depends on ESPRESSIF_ESP32C3
select ARCH_HAVE_BUTTONS
select ARCH_HAVE_IRQBUTTONS
---help---
The ESP32-C3 DevKit features the ESP32-C3 CPU with a RISC-V core.
It comes in two flavors, the ESP32-C3-DevKitM-1 and the ESP32-C3-DevKitC-02.
@ -450,12 +452,16 @@ config ARCH_BOARD_ESP32S3_MEADOW
config ARCH_BOARD_ESP32C6_GENERIC
bool "Espressif ESP32-C6 Generic DevKit"
depends on ESPRESSIF_ESP32C6
select ARCH_HAVE_BUTTONS
select ARCH_HAVE_IRQBUTTONS
---help---
The ESP32-C6 DevKit features the ESP32-C6 CPU with a RISC-V core.
config ARCH_BOARD_ESP32H2_GENERIC
bool "Espressif ESP32-H2 Generic DevKit"
depends on ESPRESSIF_ESP32H2
select ARCH_HAVE_BUTTONS
select ARCH_HAVE_IRQBUTTONS
---help---
The ESP32-H2 DevKit features the ESP32-H2 CPU with a RISC-V core.