From df6d45b873b7e3aae1abf7857ca06d6793652edd Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Sun, 24 May 2026 15:58:00 -0300 Subject: [PATCH 1/3] arch/sim: Add support to FTDI FT2232H as GPIO bridge This patch adds support to use FT2232H as GPIO to control external devices. Signed-off-by: Alan C. Assis --- arch/sim/Kconfig | 30 +- arch/sim/src/Makefile | 11 +- arch/sim/src/sim/CMakeLists.txt | 17 +- arch/sim/src/sim/posix/sim_ftdi_gpiochip.c | 360 ++++++++++++++++++++ arch/sim/src/sim/posix/sim_linux_gpiochip.c | 12 + arch/sim/src/sim/sim_gpiochip.c | 10 +- arch/sim/src/sim/sim_gpiochip.h | 15 +- arch/sim/src/sim/sim_internal.h | 7 +- 8 files changed, 445 insertions(+), 17 deletions(-) create mode 100644 arch/sim/src/sim/posix/sim_ftdi_gpiochip.c diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig index 7ad1e801c28be..3f836bc70b283 100644 --- a/arch/sim/Kconfig +++ b/arch/sim/Kconfig @@ -696,7 +696,7 @@ config SIM_SPIDEV_NAME endif config SIM_GPIOCHIP - bool "Simulated gpiochip" + bool "Support to Control External GPIO devices" default n depends on IOEXPANDER ---help--- @@ -709,23 +709,43 @@ choice default SIM_GPIOCHIP_LINUX config SIM_GPIOCHIP_LINUX - bool "Linux Gpiochip Character Dev" + bool "Linux GPIOCHIP Character Dev" depends on HOST_LINUX ---help--- Attach a Linux Gpiochip via the character device interface. To achieve a SPI port on Linux host, it is recommended to use a USB<>GPIO device such as CH341A/B. +config SIM_GPIOCHIP_FTDI + bool "FTDI I/O Expander (i.e. FT2232H) as GPIOCHIP" + ---help--- + It is possible to use a USB FTDI FTDI to support external + devices connected to the computer. These devices could be GPIO, + I2C or SPI and NuttX on SIM will see it as a real device. + endchoice config SIM_GPIOCHIP_NAME string "the name of host gpiochip dev to attach to simulator" default "/dev/gpiochip0" + depends on SIM_GPIOCHIP_LINUX ---help--- - This is the name of the gpiochip device on the host implementation to - attach to the simulator driver. + This is the name of the gpiochip device on the host + implementation to attach to the simulator driver. -endif +if SIM_GPIOCHIP_FTDI + +config SIM_FTDI_VID + hex "USB Vendor ID" + default 0x0403 + +config SIM_FTDI_PID + hex "USB Product ID" + default 0x6010 + +endif # SIM_FTDI + +endif # SIM_GPIOCHIP menu "Simulated UART" diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile index d238853df6fe6..0eb183b426f7c 100644 --- a/arch/sim/src/Makefile +++ b/arch/sim/src/Makefile @@ -262,9 +262,18 @@ ifeq ($(CONFIG_SIM_SPI_LINUX),y) HOSTSRCS += sim_linuxspi.c endif +ifeq ($(CONFIG_SIM_GPIOCHIP),y) + CSRCS += sim_gpiochip.c + ifeq ($(CONFIG_SIM_GPIOCHIP_LINUX),y) HOSTSRCS += sim_linux_gpiochip.c - CSRCS += sim_gpiochip.c +endif + +ifeq ($(CONFIG_SIM_GPIOCHIP_FTDI),y) + HOSTSRCS += sim_ftdi_gpiochip.c + HOSTCFLAGS += $(shell pkg-config --cflags libftdi1) + STDLIBS += $(shell pkg-config --libs libftdi1) +endif endif ifeq ($(CONFIG_SIM_USB_DEV),y) diff --git a/arch/sim/src/sim/CMakeLists.txt b/arch/sim/src/sim/CMakeLists.txt index 42c569f145e9b..c399e3193e4ae 100644 --- a/arch/sim/src/sim/CMakeLists.txt +++ b/arch/sim/src/sim/CMakeLists.txt @@ -270,9 +270,22 @@ if(CONFIG_SIM_SPI_LINUX) list(APPEND HOSTSRCS sim_linuxspi.c) endif() -if(CONFIG_SIM_GPIOCHIP_LINUX) +if(CONFIG_SIM_GPIOCHIP) list(APPEND SRCS sim_gpiochip.c) - list(APPEND HOSTSRCS sim_linux_gpiochip.c) + + if(CONFIG_SIM_GPIOCHIP_LINUX) + list(APPEND HOSTSRCS sim_linux_gpiochip.c) + endif() + + if(CONFIG_SIM_GPIOCHIP_FTDI) + list(APPEND HOSTSRCS sim_ftdi_gpiochip.c) + + find_package(PkgConfig REQUIRED) + pkg_check_modules(LIBFTDI1 REQUIRED IMPORTED_TARGET libftdi1) + + list(APPEND HOST_INCLUDE_DIRECTORIES ${LIBFTDI1_INCLUDE_DIRS}) + list(APPEND HOST_LINK_LIBRARIES PkgConfig::LIBFTDI1) + endif() endif() if(CONFIG_SIM_USB_DEV) diff --git a/arch/sim/src/sim/posix/sim_ftdi_gpiochip.c b/arch/sim/src/sim/posix/sim_ftdi_gpiochip.c new file mode 100644 index 0000000000000..06d07b3489848 --- /dev/null +++ b/arch/sim/src/sim/posix/sim_ftdi_gpiochip.c @@ -0,0 +1,360 @@ +/**************************************************************************** + * arch/sim/src/sim/posix/sim_ftdi_gpiochip.c + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sim_gpiochip.h" +#include "sim_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define GPIOCHIP_NPINS 8 + +#define gpioerr(fmt, ...) \ + syslog(LOG_ERR, "sim_ftdi_gpio: " fmt "\n", ##__VA_ARGS__) +#define gpioinfo(fmt, ...) \ + syslog(LOG_ERR, "sim_ftdi_gpio: " fmt "\n", ##__VA_ARGS__) + +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/* Host GPIOCHIP device definition */ + +struct host_gpiochip_dev +{ + struct ftdi_context *ftdi; + uint8_t port_dir; + uint8_t port_value; +}; + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: host_gpiochip_direction + * + * Description: + * Provide gpio pin direction config. + * + * Input Parameters: + * priv - A pointer to instance of Linux ft2232h_gpio. + * pin - The pin number. + * input - The direction of the pin. + * + * Returned Value: + * 0 for success, other for fail. + ****************************************************************************/ + +int host_gpiochip_direction(struct host_gpiochip_dev *priv, + uint8_t pin, bool input) +{ + struct ftdi_context *ftdi = priv->ftdi; + uint8_t dir = priv->port_dir; + + if (pin >= GPIOCHIP_NPINS) + { + gpioerr("ERROR: Invalid pin %d config\n", pin); + return -EINVAL; + } + + /* FTDI uses 1 as output and 0 as input, so invert input first */ + + input = !input; + dir &= ~(input << pin); + dir |= (input << pin); + + if (ftdi_set_bitmode(ftdi, dir, BITMODE_SYNCBB) < 0) + { + gpioerr("Failed to change pin %d direction\n", pin); + return -EIO; + } + + priv->port_dir = dir; + + return 0; +} + +/**************************************************************************** + * Name: host_gpiochip_irq_request + * + * Input Parameters: + * priv - A pointer to instance of Linux gpiochip. + * pin - The pin number. + * cfgset - The config set of the pin. + * + * Returned Value: + * 0 for success, other for fail. + ****************************************************************************/ + +int host_gpiochip_irq_request(struct host_gpiochip_dev *priv, uint8_t pin, + uint16_t cfg) +{ + return 0; +} + +/**************************************************************************** + * Name: host_gpiochip_writepin + * + * Description: + * Write ft2232h_gpio pin value. + * + * Input Parameters: + * priv - A pointer to instance of Linux ft2232h_gpio. + * pin - The pin number. + * value - The value write to the pin. + * + * Returned Value: + * 0 for success, other for fail. + ****************************************************************************/ + +int host_gpiochip_writepin(struct host_gpiochip_dev *priv, + uint8_t pin, bool value) +{ + struct ftdi_context *ftdi = priv->ftdi; + uint8_t pins = priv->port_value; + + if (pin >= GPIOCHIP_NPINS) + { + gpioerr("ERROR: Invalid pin %d config\n", pin); + return -EINVAL; + } + + pins &= ~(value << pin); + pins |= (value << pin); + ftdi_write_data(ftdi, &pins, 1); + priv->port_value = pins; + + return 0; +} + +/**************************************************************************** + * Name: host_gpiochip_readpin + * + * Description: + * Read ft2232h_gpio pin value. + * + * Input Parameters: + * priv - A pointer to instance of Linux ft2232h_gpio. + * pin - The pin number. + * value - The value write to the pin. + * + * Returned Value: + * 0 for success, other for fail. + ****************************************************************************/ + +int host_gpiochip_readpin(struct host_gpiochip_dev *priv, + uint8_t pin, bool *value) +{ + struct ftdi_context *ftdi = priv->ftdi; + uint8_t pins; + + if (pin >= GPIOCHIP_NPINS) + { + gpioerr("ERROR: Invalid pin %d config\n", pin); + return -EINVAL; + } + + ftdi_read_pins(ftdi, &pins); + priv->port_value = pins; + + *value = !!(pins & (1 << pin)); + + return 0; +} + +/**************************************************************************** + * Name: host_gpiochip_irq_active + * + * Description: + * register gpio for gpiochip device + * + * Input Parameters: + * priv - A pointer to instance of Linux gpiochip. + * pin - gpio pin of Linux gpiochip device. + * + * Returned Value: + * 0 for OK. + * + ****************************************************************************/ + +bool host_gpiochip_irq_active(struct host_gpiochip_dev *priv, uint8_t pin) +{ + return false; +} + +/**************************************************************************** + * Name: host_gpiochip_get_line + * + * Description: + * Get line info from ft2232h_gpio device + * + * Input Parameters: + * priv - A pointer to instance of Linux ft2232h_gpio. + * pin - gpio line of Linux ft2232h_gpio. + * input - A pointer to direction of gpioline. + * + * Returned Value: + * 0 for OK. + * + ****************************************************************************/ + +int host_gpiochip_get_line(struct host_gpiochip_dev *priv, + uint8_t pin, bool *input) +{ + uint8_t dir = priv->port_dir; + + if (pin >= GPIOCHIP_NPINS) + { + gpioerr("ERROR: Invalid pin %d config\n", pin); + return -EINVAL; + } + + /* For FTDI Input is defined as 0, so we need to invert here */ + + *input = !(dir & (1 << pin)); + + return 0; +} + +/**************************************************************************** + * Name: host_gpiochip_alloc + * + * Description: + * Initialize one ft2232h_gpio device + * + * Input Parameters: + * None + * + * Returned Value: + * The pointer to the instance of Linux ft2232h_gpio device. + * + ****************************************************************************/ + +struct host_gpiochip_dev *host_gpiochip_alloc(uint8_t pins_dir) +{ + struct host_gpiochip_dev *dev; + + dev = malloc(sizeof(struct host_gpiochip_dev)); + if (!dev) + { + gpioerr("Failed to allocate memory for ft2232h_gpio device"); + return NULL; + } + + dev->ftdi = ftdi_new(); + if (dev->ftdi == NULL) + { + gpioerr("Failed to initialize the new FTDI device!\n"); + free(dev); + return NULL; + } + + /* Interface A controls AD0-AD7 pins on SYNCBB mode */ + + ftdi_set_interface(dev->ftdi, INTERFACE_A); + + /* Open the device */ + + if (ftdi_usb_open(dev->ftdi, CONFIG_SIM_FTDI_VID, + CONFIG_SIM_FTDI_PID) < 0) + { + gpioerr("Failed to open the FTDI FT2232H device!\n"); + ftdi_free(dev->ftdi); + free(dev); + return NULL; + } + + /* Reset the Bitmode */ + + ftdi_set_bitmode(dev->ftdi, 0x00, BITMODE_RESET); + + /* Configure SYNCBB mode with the pins direction */ + + if (ftdi_set_bitmode(dev->ftdi, pins_dir, BITMODE_SYNCBB) < 0) + { + gpioerr("Failed to enter SYNCBB mode\n"); + ftdi_usb_close(dev->ftdi); + ftdi_free(dev->ftdi); + free(dev); + return NULL; + } + + /* Save the current pins direction */ + + dev->port_dir = pins_dir; + dev->port_value = 0x00; + + return dev; +} + +/**************************************************************************** + * Name: host_gpiochip_free + * + * Description: + * Uninitialize an ft2232h_gpio device + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void host_gpiochip_free(struct host_gpiochip_dev *priv) +{ + ftdi_set_bitmode(priv->ftdi, 0x00, BITMODE_RESET); + ftdi_usb_close(priv->ftdi); + ftdi_free(priv->ftdi); + free(priv); +} + diff --git a/arch/sim/src/sim/posix/sim_linux_gpiochip.c b/arch/sim/src/sim/posix/sim_linux_gpiochip.c index e6bdd25264702..a94556f17cefa 100644 --- a/arch/sim/src/sim/posix/sim_linux_gpiochip.c +++ b/arch/sim/src/sim/posix/sim_linux_gpiochip.c @@ -50,6 +50,18 @@ #define gpioinfo(fmt, ...) \ syslog(LOG_ERR, "sim_linux_gpiochip: " fmt "\n", ##__VA_ARGS__) +/**************************************************************************** + * Type Definitions + ****************************************************************************/ + +/* Host GPIOCHIP device definition */ + +struct host_gpiochip_dev +{ + int file; + int line_fd[CONFIG_IOEXPANDER_NPINS]; +}; + /**************************************************************************** * Private Types ****************************************************************************/ diff --git a/arch/sim/src/sim/sim_gpiochip.c b/arch/sim/src/sim/sim_gpiochip.c index 52906811888a1..e68c6ac707278 100644 --- a/arch/sim/src/sim/sim_gpiochip.c +++ b/arch/sim/src/sim/sim_gpiochip.c @@ -418,7 +418,11 @@ static void sim_gpiochip_interrupt(wdparm_t arg) * ****************************************************************************/ -int sim_gpiochip_initialize(const char *path) +#ifdef CONFIG_SIM_GPIOCHIP_FTDI + int sim_gpiochip_initialize(uint8_t pins_dir) +#else + int sim_gpiochip_initialize(const char *path) +#endif { struct sim_gpiochip_dev_s *priv; int ret; @@ -432,7 +436,11 @@ int sim_gpiochip_initialize(const char *path) priv->ops = &g_sim_gpiochip_ops; +#ifdef CONFIG_SIM_GPIOCHIP_FTDI + priv->dev = host_gpiochip_alloc(pins_dir); +#else priv->dev = host_gpiochip_alloc(path); +#endif if (priv->dev == NULL) { gpioerr("Failed to init gpiochip: %d", ret); diff --git a/arch/sim/src/sim/sim_gpiochip.h b/arch/sim/src/sim/sim_gpiochip.h index 43bdf3b672fc3..12044e4c6de85 100644 --- a/arch/sim/src/sim/sim_gpiochip.h +++ b/arch/sim/src/sim/sim_gpiochip.h @@ -44,17 +44,18 @@ * Type Definitions ****************************************************************************/ -struct host_gpiochip_dev -{ - int file; - int line_fd[CONFIG_IOEXPANDER_NPINS]; -}; +/* Host GPIOCHIP Device declared for sim_gpiochip.c */ + +struct host_gpiochip_dev; /**************************************************************************** * Public Function Prototypes ****************************************************************************/ - -struct host_gpiochip_dev *host_gpiochip_alloc(const char *filename); +#ifdef CONFIG_SIM_GPIOCHIP_FTDI + struct host_gpiochip_dev *host_gpiochip_alloc(uint8_t pins_dir); +#else + struct host_gpiochip_dev *host_gpiochip_alloc(const char *filename); +#endif void host_gpiochip_free(struct host_gpiochip_dev *dev); int host_gpiochip_get_line(struct host_gpiochip_dev *priv, uint8_t pin, bool *input); diff --git a/arch/sim/src/sim/sim_internal.h b/arch/sim/src/sim/sim_internal.h index 3ca70b65e9421..2e44b150800d0 100644 --- a/arch/sim/src/sim/sim_internal.h +++ b/arch/sim/src/sim/sim_internal.h @@ -502,10 +502,15 @@ size_t sim_stack_check(void *alloc, size_t size); void sim_stack_color(void *stackbase, size_t nbytes); #endif -#ifdef CONFIG_SIM_GPIOCHIP +#ifdef CONFIG_SIM_GPIOCHIP_LINUX int sim_gpiochip_initialize(const char *filename); struct ioexpander_dev_s *sim_gpiochip_get_ioe(void); #endif +#ifdef CONFIG_SIM_GPIOCHIP_FTDI +int sim_gpiochip_initialize(uint8_t pins_dir); +struct ioexpander_dev_s *sim_gpiochip_get_ioe(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* __ARCH_SIM_SRC_SIM_INTERNAL_H */ From 1368ed295ce659d0650b7a3d61165813eac4c7e2 Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Sun, 24 May 2026 16:43:16 -0300 Subject: [PATCH 2/3] doc/sim: Add documentation about FT2232H GPIO integration This commit add documentation to explain about the FT2232H integration on NuttX. Signed-off-by: Alan C. Assis --- Documentation/platforms/sim/index.rst | 1 + .../platforms/sim/sim/boards/sim/index.rst | 21 ++ .../platforms/sim/sim_ft2232h_gpio.rst | 209 ++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 Documentation/platforms/sim/sim_ft2232h_gpio.rst diff --git a/Documentation/platforms/sim/index.rst b/Documentation/platforms/sim/index.rst index 84adbf17c8a3f..26642be6dbd06 100644 --- a/Documentation/platforms/sim/index.rst +++ b/Documentation/platforms/sim/index.rst @@ -15,3 +15,4 @@ The following Simulator/Emulators are supported: network_linux network_vpnkit sim_gpiochip + sim_ft2232h_gpio diff --git a/Documentation/platforms/sim/sim/boards/sim/index.rst b/Documentation/platforms/sim/sim/boards/sim/index.rst index c2487ba2ed937..4cc128040f874 100644 --- a/Documentation/platforms/sim/sim/boards/sim/index.rst +++ b/Documentation/platforms/sim/sim/boards/sim/index.rst @@ -651,6 +651,27 @@ fb A simple configuration used for some basic (non-graphic) debug of the framebuffer character drivers using ``apps/examples/fb``. +ft2232h_gpio +------------ + +This example requires you have a FT2232H I/O Expander board (i.e. CJMCU-2232HL) +connected to your host computer (read the "Sim FTDI GPIO Driver" documentation) +to read/write external GPIO pins. + +Usage example: + +.. code:: console + + nsh> gpio -o 1 /dev/gpio20 + Driver: /dev/gpio20 + Input pin: Value=1 + nsh> gpio -o 1 /dev/gpio27 + Driver: /dev/gpio27 + Output pin: Value=0 + Writing: Value=1 + Verify: Value=1 + nsh> + ipforward --------- diff --git a/Documentation/platforms/sim/sim_ft2232h_gpio.rst b/Documentation/platforms/sim/sim_ft2232h_gpio.rst new file mode 100644 index 0000000000000..b5c7f85b1e12a --- /dev/null +++ b/Documentation/platforms/sim/sim_ft2232h_gpio.rst @@ -0,0 +1,209 @@ +===================================== +Sim FTDI GPIO Driver (Using libftdi1) +===================================== + +Overview +======== + +The NuttX simulation (sim) already has a GPIO Chip driver that provides a mechanism use GPIO to control external devices. However that solution depends on having a driver to Linux side and that adds more overhead. + +This FTDI driver allows a direct use of libftdi1 to control up to 8 GPIOs. + +This driver is particularly useful for: + +- Testing GPIO-based applications in a simulated environment with real hardware +- Interfacing with USB-to-GPIO adapters from NuttX simulation +- Developing and debugging GPIO drivers without dedicated embedded hardware + +Host Prepare +============ + +Preparation required on the host side: + +- Hardware module required: FT2232H module like the CJMCU-2232HL module +- A udev rule on Linux side to avoid using the FT2232H as USB/Serial: + +.. code-block:: console + + $ cat /etc/udev/rules.d/99-ft2232h-d2xx.rules + ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", ATTRS{product}=="FTDI Device", MODE="0666" + +- The libftdi1-dev installed on your system. + +Architecture +============ + +The driver consists of two layers: + +1. **NuttX Layer** (``sim_gpiochip.c``): Implements the NuttX ``ioexpander_dev_s`` + interface, providing standard GPIO operations to upper-layer NuttX drivers. + +2. **Host Layer** (``sim_ftdi_gpiochip.c``): Interfaces directly with libftdio1 to initialize and to provide the functions to control the GPIOs. + +.. uml:: + + @startuml + skinparam componentStyle rectangle + skinparam defaultFontName Monospaced + + [NuttX Application] as app + [GPIO Lower Half\n(gpio_lower_half)] as gpio + [sim_gpiochip.c\n(ioexpander_dev_s)] as ioex + note right of ioex : NuttX ioexpander interface + [sim_ftdi_gpiochip.c\n(host interface)] as sim + note right of sim : Linux host GPIO interface + [libftdi1] as ftdi + note right of ftdi : Linux library to control FT2232H + + app --> gpio + gpio --> ioex + ioex --> sim + sim --> ftdi + @enduml + +Header Files +============ + +- ``arch/sim/src/sim/sim_gpiochip.h``: Host GPIO chip interface definitions and function prototypes. + +- ``include/nuttx/ioexpander/ioexpander.h``: Standard NuttX IO expander interface. + +- ``include/nuttx/ioexpander/gpio.h``: NuttX GPIO interface definitions. + +Configuration Options +===================== + +The following configuration options are relevant to this driver: + +- ``CONFIG_SIM_GPIOCHIP_FTDI``: Enable the FTDI/FT2232H driver support. + +Supported Operations +==================== + +The driver supports the following GPIO operations: + +Direction Control +----------------- + +.. code-block:: c + + int sim_gpiochip_direction(struct ioexpander_dev_s *dev, + uint8_t pin, int direction); + +Set GPIO pin direction. Supported directions: + +- ``IOEXPANDER_DIRECTION_IN``: Configure as input +- ``IOEXPANDER_DIRECTION_OUT``: Configure as output +- ``IOEXPANDER_DIRECTION_OUT_OPENDRAIN``: Configure as open-drain output + +Read/Write Pin +-------------- + +.. code-block:: c + + int sim_gpiochip_readpin(struct ioexpander_dev_s *dev, uint8_t pin, + bool *value); + int sim_gpiochip_writepin(struct ioexpander_dev_s *dev, uint8_t pin, + bool value); + +Read or write the value of a GPIO pin. + +Host Layer API +============== + +The host layer (``sim_ftdi_gpiochip.c``) provides the following functions: + +.. code-block:: c + + /* Allocate and initialize a host GPIO chip device */ + struct host_gpiochip_dev *host_gpiochip_alloc(uint8_t pins_dir); + + /* Free a host GPIO chip device */ + void host_gpiochip_free(struct host_gpiochip_dev *dev); + + /* Set GPIO pin direction */ + int host_gpiochip_direction(struct host_gpiochip_dev *dev, + uint8_t pin, bool input); + + /* Read GPIO pin value */ + int host_gpiochip_readpin(struct host_gpiochip_dev *dev, + uint8_t pin, bool *value); + + /* Write GPIO pin value */ + int host_gpiochip_writepin(struct host_gpiochip_dev *dev, + uint8_t pin, bool value); + + /* Request GPIO interrupt */ + int host_gpiochip_irq_request(struct host_gpiochip_dev *dev, + uint8_t pin, uint16_t cfgset); + + /* Check if GPIO interrupt is active */ + bool host_gpiochip_irq_active(struct host_gpiochip_dev *dev, uint8_t pin); + + /* Get GPIO line information */ + int host_gpiochip_get_line(struct host_gpiochip_dev *priv, + uint8_t pin, bool *input); + +Linux Kernel Version Requirements +================================= + +The driver uses Linux GPIO v2 ABI, which requires: + +- **Linux kernel >= 6.8.0**: Full functionality with GPIO v2 API support. +- **Linux kernel < 6.8.0**: The driver compiles but provides stub implementations + that return 0 or NULL. + +Usage Example +============= + +Initialization +-------------- + +Application Usage +----------------- + +After initialization, GPIO pins can be accessed through standard NuttX GPIO interface: + +.. code-block:: c + + #include + #include + #include + + int main(void) + { + int fd; + bool value; + + /* Open GPIO device */ + fd = open("/dev/gpio20", O_RD); + if (fd < 0) + { + return -1; + } + + /* Read GPIO value */ + ioctl(fd, GPIOC_READ, &value); + printf("GPIO value: %d\n", value); + + close(fd); + return 0; + } + +Files +===== + +- ``arch/sim/src/sim/sim_gpiochip.c``: NuttX IO expander implementation +- ``arch/sim/src/sim/posix/sim_ftdi_gpiochip.c``: Linux host GPIO interface +- ``arch/sim/src/sim/sim_gpiochip.h``: Host GPIO chip header file + +Limitations +=========== + +1. **Polling-based interrupts**: Due to simulation constraints, interrupts are + implemented using polling rather than true hardware interrupts. + +3. **Pin count**: Limited to 8 pins of SYNBB AD0-7. + +4. **Invert option**: The ``IOEXPANDER_OPTION_INVERT`` option is not yet implemented. + From 80de8dc42e5fe4942ad858aab32d6bd537e0d030 Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Sun, 24 May 2026 17:04:37 -0300 Subject: [PATCH 3/3] boards/sim: Add FT2232H GPIO board support This board profile configure the FT2232H module to use as a GPIO to NuttX sim. Signed-off-by: Alan C. Assis --- .../sim/sim/configs/ft2232h_gpio/defconfig | 76 +++++++++++++++++++ boards/sim/sim/sim/src/sim_bringup.c | 19 +++++ 2 files changed, 95 insertions(+) create mode 100644 boards/sim/sim/sim/configs/ft2232h_gpio/defconfig diff --git a/boards/sim/sim/sim/configs/ft2232h_gpio/defconfig b/boards/sim/sim/sim/configs/ft2232h_gpio/defconfig new file mode 100644 index 0000000000000..328efb67dccfa --- /dev/null +++ b/boards/sim/sim/sim/configs/ft2232h_gpio/defconfig @@ -0,0 +1,76 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="sim" +CONFIG_ARCH_BOARD="sim" +CONFIG_ARCH_BOARD_SIM=y +CONFIG_ARCH_CHIP="sim" +CONFIG_ARCH_SIM=y +CONFIG_BOARDCTL_APP_SYMTAB=y +CONFIG_BOARDCTL_POWEROFF=y +CONFIG_BOARD_LOOPSPERMSEC=0 +CONFIG_BOOT_RUNFROMEXTSRAM=y +CONFIG_BUILTIN=y +CONFIG_COVERAGE_ALL=y +CONFIG_COVERAGE_TOOLCHAIN=y +CONFIG_DEBUG_ASSERTIONS=y +CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEV_GPIO=y +CONFIG_DEV_LOOP=y +CONFIG_ETC_FATDEVNO=2 +CONFIG_ETC_ROMFS=y +CONFIG_ETC_ROMFSDEVNO=1 +CONFIG_EXAMPLES_GPIO=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_FAT_LCNAMES=y +CONFIG_FAT_LFN=y +CONFIG_FS_BINFS=y +CONFIG_FS_FAT=y +CONFIG_FS_HOSTFS=y +CONFIG_FS_PROCFS=y +CONFIG_FS_RAMMAP=y +CONFIG_FS_ROMFS=y +CONFIG_GPIO_LOWER_HALF=y +CONFIG_HAVE_CXXINITIALIZE=y +CONFIG_IDLETHREAD_STACKSIZE=4096 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_IOEXPANDER=y +CONFIG_IOEXPANDER_DUMMY=y +CONFIG_LIBC_ENVPATH=y +CONFIG_LIBC_EXECFUNCS=y +CONFIG_LIBC_LOCALE=y +CONFIG_LIBC_LOCALE_CATALOG=y +CONFIG_LIBC_LOCALE_GETTEXT=y +CONFIG_LIBC_MAX_EXITFUNS=1 +CONFIG_LIBC_NUMBERED_ARGS=y +CONFIG_NDEBUG=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILE_APPS=y +CONFIG_NSH_READLINE=y +CONFIG_PATH_INITIAL="/bin" +CONFIG_PIPES=y +CONFIG_PSEUDOFS_ATTRIBUTES=y +CONFIG_PSEUDOFS_FILE=y +CONFIG_PSEUDOFS_SOFTLINKS=y +CONFIG_READLINE_TABCOMPLETION=y +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_EVENTS=y +CONFIG_SCHED_HAVE_PARENT=y +CONFIG_SCHED_WAITPID=y +CONFIG_SIM_GPIOCHIP=y +CONFIG_SIM_GPIOCHIP_FTDI=y +CONFIG_SIM_HOSTFS=y +CONFIG_SIM_WALLTIME_SIGNAL=y +CONFIG_START_MONTH=6 +CONFIG_START_YEAR=2008 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_GCOV=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_OSTEST=y diff --git a/boards/sim/sim/sim/src/sim_bringup.c b/boards/sim/sim/sim/src/sim_bringup.c index c839d22333220..c785e89a0735c 100644 --- a/boards/sim/sim/sim/src/sim_bringup.c +++ b/boards/sim/sim/sim/src/sim_bringup.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,10 @@ #include #endif +#ifdef CONFIG_SIM_GPIOCHIP_FTDI +#include "sim_gpiochip.h" +#endif + #include "sim_internal.h" #include "sim.h" @@ -122,6 +127,20 @@ int sim_bringup(void) #endif int ret = OK; +#ifdef CONFIG_SIM_GPIOCHIP_FTDI + /* Initialize the FT2232H GPIO device + * pass a parameter defining which pins will be input (0) and + * which will be output (1). + * 0xf0 = AD0-AD3: Input; AD4-AD7: Output. + */ + + ret = sim_gpiochip_initialize(0xf0); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to initialize FT2232H: %d\n", ret); + } +#endif + #ifdef CONFIG_FS_BINFS /* Mount the binfs file system */