diff --git a/arch/risc-v/include/espressif/.gitignore b/arch/risc-v/include/espressif/.gitignore index 4cebf84fe7..a9e61e717e 100644 --- a/arch/risc-v/include/espressif/.gitignore +++ b/arch/risc-v/include/espressif/.gitignore @@ -1 +1,2 @@ +/gpio_sig_map.h /irq.h diff --git a/arch/risc-v/src/espressif/Kconfig b/arch/risc-v/src/espressif/Kconfig index dfd0c2ed14..311daa7061 100644 --- a/arch/risc-v/src/espressif/Kconfig +++ b/arch/risc-v/src/espressif/Kconfig @@ -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 diff --git a/arch/risc-v/src/espressif/Make.defs b/arch/risc-v/src/espressif/Make.defs index 5d4972387f..e4f3d10bbb 100644 --- a/arch/risc-v/src/espressif/Make.defs +++ b/arch/risc-v/src/espressif/Make.defs @@ -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)) diff --git a/arch/risc-v/src/espressif/esp_gpio.c b/arch/risc-v/src/espressif/esp_gpio.c index e8853b4129..beb0526a93 100644 --- a/arch/risc-v/src/espressif/esp_gpio.c +++ b/arch/risc-v/src/espressif/esp_gpio.c @@ -22,20 +22,33 @@ * Included Files ****************************************************************************/ +/* Config */ + #include +/* Libc */ + #include #include #include #include +/* NuttX */ + #include #include #include +/* 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 diff --git a/arch/risc-v/src/espressif/esp_gpio.h b/arch/risc-v/src/espressif/esp_gpio.h index ce49d562f2..cac9aae8ca 100644 --- a/arch/risc-v/src/espressif/esp_gpio.h +++ b/arch/risc-v/src/espressif/esp_gpio.h @@ -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 diff --git a/arch/risc-v/src/espressif/esp_irq.c b/arch/risc-v/src/espressif/esp_irq.c index f43a1532ff..6b294bd19c 100644 --- a/arch/risc-v/src/espressif/esp_irq.c +++ b/arch/risc-v/src/espressif/esp_irq.c @@ -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(); diff --git a/arch/risc-v/src/espressif/hal_esp32c3.mk b/arch/risc-v/src/espressif/hal_esp32c3.mk index 6086572711..2fe17c718a 100644 --- a/arch/risc-v/src/espressif/hal_esp32c3.mk +++ b/arch/risc-v/src/espressif/hal_esp32c3.mk @@ -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 diff --git a/arch/risc-v/src/espressif/hal_esp32c6.mk b/arch/risc-v/src/espressif/hal_esp32c6.mk index 516df9d218..a50dee95f4 100644 --- a/arch/risc-v/src/espressif/hal_esp32c6.mk +++ b/arch/risc-v/src/espressif/hal_esp32c6.mk @@ -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 diff --git a/arch/risc-v/src/espressif/hal_esp32h2.mk b/arch/risc-v/src/espressif/hal_esp32h2.mk index 04e72255ce..5c59436dfc 100644 --- a/arch/risc-v/src/espressif/hal_esp32h2.mk +++ b/arch/risc-v/src/espressif/hal_esp32h2.mk @@ -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 diff --git a/boards/Kconfig b/boards/Kconfig index df5fa945e6..660259cfae 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -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.