This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit edf7c1de6a398e3d15ea15308c4c98c6152ecc2d Author: Filipe Cavalcanti <[email protected]> AuthorDate: Tue Aug 25 14:18:29 2026 -0300 boards/risc-v: GPIO support on esp32p4-tab5 Adds GPIO defconfig on M5Stack Tab5. The example has one GPIO output and one GPIO interrupt. Signed-off-by: Filipe Cavalcanti <[email protected]> --- boards/risc-v/esp32p4/esp32p4-tab5/include/board.h | 13 + boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs | 4 + .../risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h | 18 + .../esp32p4/esp32p4-tab5/src/esp32p4_bringup.c | 10 + .../risc-v/esp32p4/esp32p4-tab5/src/esp32p4_gpio.c | 544 +++++++++++++++++++++ 5 files changed, 589 insertions(+) diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h b/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h index 07b0b78f387..9758200e99f 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h +++ b/boards/risc-v/esp32p4/esp32p4-tab5/include/board.h @@ -90,6 +90,19 @@ # define TAB5_MIPI_DSI_LANE_BITRATE_MBPS 965 #endif +/* GPIOs available on the M5-Bus connector */ + +#define TAB5_GPIO_MBUS_3 3 +#define TAB5_GPIO_MBUS_2 2 +#define TAB5_GPIO_MBUS_47 47 + +#define TAB5_GPIO_MBUS_16 16 +#define TAB5_GPIO_MBUS_45 45 +#define TAB5_GPIO_MBUS_4 4 +#define TAB5_GPIO_MBUS_48 48 +#define TAB5_GPIO_MBUS_35 35 +#define TAB5_GPIO_MBUS_51 51 + /* Touch - ST7121/ST7123 TDDI @0x55 (NOT implemented; INT GPIO23). Older * ILI9881 units used GT911 @0x14 on the same INT pin. */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs b/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs index 34610b8add7..b1537ba3531 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/Make.defs @@ -55,6 +55,10 @@ ifeq ($(CONFIG_BOARDCTL),y) endif endif +ifeq ($(CONFIG_DEV_GPIO),y) + CSRCS += esp32p4_gpio.c +endif + DEPPATH += --dep-path board VPATH += :board CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h index f9d94bc21a5..ed149606e4a 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4-tab5.h @@ -63,6 +63,24 @@ int esp_bringup(void); +/**************************************************************************** + * Name: esp_gpio_init + * + * Description: + * Configure the GPIO driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK). + * + ****************************************************************************/ + +#ifdef CONFIG_DEV_GPIO +int esp_gpio_init(void); +#endif + #ifdef CONFIG_ESP32P4_TAB5_LCD_POWER /**************************************************************************** diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c index de8a71032b3..850ea1e3b62 100644 --- a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_bringup.c @@ -109,6 +109,16 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_DEV_GPIO + /* Configure the GPIO driver */ + + ret = esp_gpio_init(); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize GPIO driver: %d\n", ret); + } +#endif + #ifdef CONFIG_ESP32P4_TAB5_IOEXPANDER /* Initialize the IO expanders */ diff --git a/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_gpio.c b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_gpio.c new file mode 100644 index 00000000000..2d979a5f206 --- /dev/null +++ b/boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_gpio.c @@ -0,0 +1,544 @@ +/**************************************************************************** + * boards/risc-v/esp32p4/esp32p4-tab5/src/esp32p4_gpio.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/types.h> +#include <syslog.h> +#include <assert.h> +#include <nuttx/debug.h> + +#include <arch/irq.h> +#include <nuttx/irq.h> +#include <nuttx/ioexpander/gpio.h> + +#include "espressif/esp_gpio.h" +#ifdef CONFIG_ESPRESSIF_DEDICATED_GPIO +#include "espressif/esp_dedic_gpio.h" +#endif +#include "espressif/esp_rtc_gpio.h" + +#include <arch/chip/gpio_sig_map.h> + +#include "esp32p4-tab5.h" +#include <arch/board/board.h> + +#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if !defined(CONFIG_ESPRESSIF_GPIO_IRQ) && BOARD_NGPIOINT > 0 +# error "NGPIOINT is > 0 and GPIO interrupts aren't enabled" +#endif + +/* Output Pins */ + +#define GPIO_OUT1 TAB5_GPIO_MBUS_2 +#define BOARD_NGPIOOUT 1 + +/* Interrupt Pins */ + +#define GPIO_IRQ1 TAB5_GPIO_MBUS_3 +#define BOARD_NGPIOINT 1 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct espgpio_dev_s +{ + struct gpio_dev_s gpio; + uint8_t id; +}; + +struct espgpint_dev_s +{ + struct espgpio_dev_s espgpio; + pin_interrupt_t callback; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#if BOARD_NGPIOOUT > 0 +static int gpout_read(struct gpio_dev_s *dev, bool *value); +static int gpout_write(struct gpio_dev_s *dev, bool value); +static int gpout_setpintype(struct gpio_dev_s *dev, + enum gpio_pintype_e pintype); +#endif + +#if BOARD_NGPIOINT > 0 +static int gpint_read(struct gpio_dev_s *dev, bool *value); +static int gpint_attach(struct gpio_dev_s *dev, + pin_interrupt_t callback); +static int gpint_enable(struct gpio_dev_s *dev, bool enable); +static int gpint_setpintype(struct gpio_dev_s *dev, + enum gpio_pintype_e pintype); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if BOARD_NGPIOOUT > 0 +static const struct gpio_operations_s gpout_ops = +{ + .go_read = gpout_read, + .go_write = gpout_write, + .go_attach = NULL, + .go_enable = NULL, + .go_setpintype = gpout_setpintype, +}; + +/* This array maps the GPIO pins used as OUTPUT */ + +static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] = +{ + GPIO_OUT1 +}; + +static struct espgpio_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, + .go_setpintype = gpint_setpintype, +}; + +/* This array maps the GPIO pins used as INTERRUPT INPUTS */ + +static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] = +{ + GPIO_IRQ1, +}; + +static struct espgpint_dev_s g_gpint[BOARD_NGPIOINT]; +#endif + +/* This array maps the GPIO pins used as Dedicated GPIO */ + +#ifdef CONFIG_ESPRESSIF_DEDICATED_GPIO +static const int g_gpioidedic[GPIO_DEDIC_COUNT] = +{ + GPIO_DEDIC1, GPIO_DEDIC2 +}; + +static struct esp_dedic_gpio_flags_s dedic_gpio_flags = +{ + .input_enable = 1, + .invert_input_enable = 0, + .output_enable = 1, + .invert_output_enable = 0 +}; + +struct esp_dedic_gpio_config_s dedic_gpio_conf = +{ + .gpio_array = g_gpioidedic, + .array_size = GPIO_DEDIC_COUNT, + .flags = &dedic_gpio_flags, + .path = "/dev/dedic_gpio0" +}; + +struct file *dedicated_gpio = NULL; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: gpout_read + * + * Description: + * Read a digital output pin. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * value - A pointer to store the state of the pin. + * + * Returned Value: + * Zero (OK). + * + ****************************************************************************/ + +#if BOARD_NGPIOOUT > 0 +static int gpout_read(struct gpio_dev_s *dev, bool *value) +{ + struct espgpio_dev_s *espgpio = (struct espgpio_dev_s *)dev; + + DEBUGASSERT(espgpio != NULL && value != NULL); + DEBUGASSERT(espgpio->id < BOARD_NGPIOOUT); + gpioinfo("Reading...\n"); + + *value = esp_gpioread(g_gpiooutputs[espgpio->id]); + return OK; +} + +/**************************************************************************** + * Name: gpout_write + * + * Description: + * Write to a digital output pin. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * value - The value to be written. + * + * Returned Value: + * Zero (OK). + * + ****************************************************************************/ + +static int gpout_write(struct gpio_dev_s *dev, bool value) +{ + struct espgpio_dev_s *espgpio = (struct espgpio_dev_s *)dev; + + DEBUGASSERT(espgpio != NULL); + DEBUGASSERT(espgpio->id < BOARD_NGPIOOUT); + gpioinfo("Writing %d\n", (int)value); + + esp_gpiowrite(g_gpiooutputs[espgpio->id], value); + return OK; +} + +/**************************************************************************** + * Name: gpout_setpintype + * + * Description: + * Set digital output pin type. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * pintype - The pin type. See nuttx/ioexpander/gpio.h. + * + * Returned Value: + * Zero (OK) on success; -1 (ERROR) otherwise. + * + ****************************************************************************/ + +static int gpout_setpintype(struct gpio_dev_s *dev, + enum gpio_pintype_e pintype) +{ + struct espgpio_dev_s *espgpio = (struct espgpio_dev_s *)dev; + + DEBUGASSERT(espgpio != NULL); + DEBUGASSERT(espgpio->id < BOARD_NGPIOOUT); + gpioinfo("Setting pintype: %d\n", (int)pintype); + + esp_gpio_matrix_out(g_gpiooutputs[espgpio->id], + SIG_GPIO_OUT_IDX, 0, 0); + + switch (pintype) + { + case GPIO_INPUT_PIN: + esp_configgpio(g_gpiooutputs[espgpio->id], INPUT); + break; + case GPIO_INPUT_PIN_PULLUP: + esp_configgpio(g_gpiooutputs[espgpio->id], INPUT_PULLUP); + break; + case GPIO_INPUT_PIN_PULLDOWN: + esp_configgpio(g_gpiooutputs[espgpio->id], INPUT_PULLDOWN); + break; + case GPIO_OUTPUT_PIN: + esp_configgpio(g_gpiooutputs[espgpio->id], INPUT | OUTPUT); + break; + case GPIO_OUTPUT_PIN_OPENDRAIN: + esp_configgpio(g_gpiooutputs[espgpio->id], + INPUT | OUTPUT_OPEN_DRAIN); + break; + default: + return ERROR; + break; + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: espgpio_interrupt + * + * Description: + * Digital input 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. + * + ****************************************************************************/ + +#if BOARD_NGPIOINT > 0 +static int espgpio_interrupt(int irq, void *context, void *arg) +{ + struct espgpint_dev_s *espgpint = (struct espgpint_dev_s *)arg; + + DEBUGASSERT(espgpint != NULL && espgpint->callback != NULL); + gpioinfo("Interrupt! callback=%p\n", espgpint->callback); + + espgpint->callback(&espgpint->espgpio.gpio, espgpint->espgpio.id); + return OK; +} + +/**************************************************************************** + * Name: gpint_read + * + * Description: + * Read a digital input pin. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * value - A pointer to store the state of the pin. + * + * Returned Value: + * Zero (OK). + * + ****************************************************************************/ + +static int gpint_read(struct gpio_dev_s *dev, bool *value) +{ + struct espgpint_dev_s *espgpint = + (struct espgpint_dev_s *)dev; + + DEBUGASSERT(espgpint != NULL && value != NULL); + DEBUGASSERT(espgpint->espgpio.id < BOARD_NGPIOINT); + gpioinfo("Reading int pin...\n"); + + *value = esp_gpioread(g_gpiointinputs[espgpint->espgpio.id]); + return OK; +} + +/**************************************************************************** + * Name: gpint_attach + * + * Description: + * Attach the ISR to IRQ and register the callback. But it still doesn't + * enable interrupt yet. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * callback - User callback function. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +static int gpint_attach(struct gpio_dev_s *dev, + pin_interrupt_t callback) +{ + struct espgpint_dev_s *espgpint = + (struct espgpint_dev_s *)dev; + int ret; + + gpioinfo("Attaching the callback\n"); + + /* Make sure the interrupt is disabled */ + + esp_gpioirqdisable(g_gpiointinputs[espgpint->espgpio.id]); + + ret = esp_gpio_irq(g_gpiointinputs[espgpint->espgpio.id], + espgpio_interrupt, + &g_gpint[espgpint->espgpio.id]); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: gpint_attach() failed: %d\n", ret); + return ret; + } + + /* Make sure the interrupt is disabled */ + + esp_gpioirqdisable(g_gpiointinputs[espgpint->espgpio.id]); + + gpioinfo("Attach %p\n", callback); + espgpint->callback = callback; + return OK; +} + +/**************************************************************************** + * Name: gpint_enable + * + * Description: + * Enable/Disable interrupt. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * enable - True to enable, false to disable. + * + * Returned Value: + * Zero (OK). + * + ****************************************************************************/ + +static int gpint_enable(struct gpio_dev_s *dev, bool enable) +{ + struct espgpint_dev_s *espgpint = (struct espgpint_dev_s *)dev; + + if (enable) + { + if (espgpint->callback != NULL) + { + gpioinfo("Enabling the interrupt\n"); + + /* Configure the interrupt for rising edge */ + + esp_gpioirqenable(g_gpiointinputs[espgpint->espgpio.id]); + } + } + else + { + gpioinfo("Disable the interrupt\n"); + esp_gpioirqdisable(g_gpiointinputs[espgpint->espgpio.id]); + } + + return OK; +} + +/**************************************************************************** + * Name: gpint_setpintype + * + * Description: + * Set digital interrupt pin type. + * + * Parameters: + * dev - A pointer to the gpio driver struct. + * pintype - The pin type. See nuttx/ioexpander/gpio.h. + * + * Returned Value: + * Zero (OK) on success; -1 (ERROR) otherwise. + * + ****************************************************************************/ + +static int gpint_setpintype(struct gpio_dev_s *dev, + enum gpio_pintype_e pintype) +{ + struct espgpint_dev_s *espgpint = (struct espgpint_dev_s *)dev; + + DEBUGASSERT(espgpint != NULL); + DEBUGASSERT(espgpint->espgpio.id < BOARD_NGPIOINT); + gpioinfo("Setting pintype: %d\n", (int)pintype); + switch (pintype) + { + case GPIO_INTERRUPT_HIGH_PIN: + esp_configgpio(g_gpiointinputs[espgpint->espgpio.id], + INPUT_PULLUP | FALLING); + break; + case GPIO_INTERRUPT_LOW_PIN: + esp_configgpio(g_gpiointinputs[espgpint->espgpio.id], + INPUT_PULLDOWN | RISING); + break; + default: + return ERROR; + break; + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_gpio_init + * + * Description: + * Configure the GPIO driver. + * + * Returned Value: + * Zero (OK). + * + ****************************************************************************/ + +int esp_gpio_init(void) +{ + int pincount = 0; + int i; + +#if BOARD_NGPIOOUT > 0 + for (i = 0; i < BOARD_NGPIOOUT; i++) + { + /* Setup and register the GPIO pin */ + + g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN; + g_gpout[i].gpio.gp_ops = &gpout_ops; + g_gpout[i].id = i; + gpio_pin_register(&g_gpout[i].gpio, pincount); + + /* Configure the pins that will be used as output */ + + esp_gpio_matrix_out(g_gpiooutputs[i], SIG_GPIO_OUT_IDX, 0, 0); + esp_configgpio(g_gpiooutputs[i], OUTPUT_FUNCTION_2 | INPUT_FUNCTION_2); + esp_gpiowrite(g_gpiooutputs[i], 0); + + pincount++; + } +#endif + +#if BOARD_NGPIOINT > 0 + for (i = 0; i < BOARD_NGPIOINT; i++) + { + /* Setup and register the GPIO pin */ + + g_gpint[i].espgpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN; + g_gpint[i].espgpio.gpio.gp_ops = &gpint_ops; + g_gpint[i].espgpio.id = i; + gpio_pin_register(&g_gpint[i].espgpio.gpio, pincount); + + /* Configure the pins that will be used as interrupt input with + * falling edge. + */ + + esp_configgpio(g_gpiointinputs[i], + INPUT_FUNCTION_2 | PULLUP | FALLING); + + pincount++; + } +#endif + +#ifdef CONFIG_ESPRESSIF_DEDICATED_GPIO + dedicated_gpio = esp_dedic_gpio_new_bundle(&dedic_gpio_conf); + + pincount++; +#endif + + return OK; +} +#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */
