[PATCH v6 07/10] bsps: Add GPIO API

Duc Doan dtbpkmte at gmail.com
Sun Aug 7 10:58:19 UTC 2022


---
 bsps/include/bsp/gpio2.h          | 524 ++++++++++++++++++++++++++++++
 bsps/shared/dev/gpio/gpio2.c      | 207 ++++++++++++
 spec/build/bsps/bspopts.yml       |   2 +
 spec/build/bsps/obj.yml           |   2 +-
 spec/build/bsps/optmaxnumgpio.yml |  16 +
 5 files changed, 750 insertions(+), 1 deletion(-)
 create mode 100644 bsps/include/bsp/gpio2.h
 create mode 100644 bsps/shared/dev/gpio/gpio2.c
 create mode 100644 spec/build/bsps/optmaxnumgpio.yml

diff --git a/bsps/include/bsp/gpio2.h b/bsps/include/bsp/gpio2.h
new file mode 100644
index 0000000000..e2a2e3b1e5
--- /dev/null
+++ b/bsps/include/bsp/gpio2.h
@@ -0,0 +1,524 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup gpio2
+ *
+ * RTEMS new GPIO API.
+ *
+ * This API is created to improve portability and simplicity for GPIO.
+ *
+ * This API maps GPIO pins into a flat numbering system, counting from 0. 
+ * This pin number is often referred to as a virtual pin number. A GPIO pin 
+ * is represented by the structure @ref rtems_gpio. This structure may also 
+ * be referred to as a "GPIO object". A "driver" could mean a BSP or a 
+ * device driver. A GPIO controller may refer to a physical GPIO controller,
+ * an ADC, a DAC, or just a group of pins that contains one or more pins.
+ *
+ */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_BSP_GPIO2_H
+#define LIBBSP_BSP_GPIO2_H
+
+#include <bsp.h>
+#include <rtems.h>
+
+/**
+  * Configure the maximum number of GPIO controllers used in
+  * a application.
+  *
+  * The macro CONFIGURE_GPIO_MAXIMUM_CONTROLLERS is a build option.
+  * If it is not defined, it will default to BSP_GPIO_NUM_CONTROLLERS. 
+  * If BSP's number of controllers is not defined, it will default
+  * to 16.
+  */
+#ifndef CONFIGURE_GPIO_MAXIMUM_CONTROLLERS
+
+#ifndef BSP_GPIO_NUM_CONTROLLERS
+#define CONFIGURE_GPIO_MAXIMUM_CONTROLLERS 16
+#else
+#define CONFIGURE_GPIO_MAXIMUM_CONTROLLERS BSP_GPIO_NUM_CONTROLLERS
+#endif /* BSP_GPIO_NUM_CONTROLLERS */
+
+#endif /* CONFIGURE_GPIO_MAXIMUM_CONTROLLERS */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+  * @brief Macro to initialize rtems_gpio.
+  *
+  * @param gpioh pointer to GPIO handlers
+  */
+#define RTEMS_GPIO_BUILD_BASE(_gpio_handlers)                   \
+    (rtems_gpio) { .virtual_pin = 0,                            \
+                   .gpio_handlers = ( _gpio_handlers )          \
+    };
+
+extern int *gpio_dummy;
+/**
+  * @brief Macro to link BSP source file.
+  *
+  * There might be a case that a BSP GPIO source file is not linked because
+  * of no reference. Use this macro to create a dummy variable to link with
+  * GPIO API. This macro should be placed outside of any function.
+  */
+#define RTEMS_GPIO_LINK()                       \
+    static int ___dummy___ = 0;                 \
+    int *gpio_dummy = &___dummy___;
+
+/**
+  * @name GPIO data structures
+  *
+  * @{
+  */
+
+/**
+  * @brief GPIO bit set and reset enumeration.
+  */
+typedef enum {
+    RTEMS_GPIO_PIN_RESET = 0,
+    RTEMS_GPIO_PIN_SET = 1
+} rtems_gpio_pin_state;
+
+/**
+  * @brief GPIO pin modes. 
+  */
+typedef enum {
+    RTEMS_GPIO_PINMODE_OUTPUT = 0,
+    RTEMS_GPIO_PINMODE_OUTPUT_PP = 0,
+    RTEMS_GPIO_PINMODE_OUTPUT_OD = 1,
+    RTEMS_GPIO_PINMODE_INPUT = 2,
+    RTEMS_GPIO_PINMODE_ANALOG = 3,
+    RTEMS_GPIO_PINMODE_BSP_SPECIFIC = 100
+} rtems_gpio_pin_mode;
+
+/**
+  * @brief GPIO pull resistor configuration. Defines pull-up or 
+  *        pull-down activation.
+  */
+typedef enum {
+    RTEMS_GPIO_NOPULL = 0,
+    RTEMS_GPIO_PULLUP = 1,
+    RTEMS_GPIO_PULLDOWN = 2,
+    RTEMS_GPIO_PULL_BSP_SPECIFIC = 100
+} rtems_gpio_pull;
+
+/**
+  * @brief Interrupt modes enumeration.
+  */
+typedef enum {
+    RTEMS_GPIO_INT_TRIG_NONE = 0,
+    RTEMS_GPIO_INT_TRIG_FALLING,
+    RTEMS_GPIO_INT_TRIG_RISING,
+    RTEMS_GPIO_INT_TRIG_BOTH_EDGES,
+    RTEMS_GPIO_INT_TRIG_LOW,
+    RTEMS_GPIO_INT_TRIG_HIGH
+} rtems_gpio_interrupt_trig;
+
+typedef struct rtems_gpio_handlers rtems_gpio_handlers;
+typedef struct rtems_gpio rtems_gpio;
+/**
+  * @brief Typedef of the function pointer of an ISR.
+  */
+typedef void (*rtems_gpio_isr)(void *);
+
+/**
+  * @brief Structure containing pointers to handlers of a
+  *        driver. Each driver must define its own 
+  *        handlers and create an object of this structure
+  *        with pointers to those handlers.
+  */
+struct rtems_gpio_handlers {
+    /**
+      * @brief Handler for setting 
+      *        pin mode. 
+      *
+      * Pin modes are from @ref rtems_gpio_pin_mode enumeration.
+      */
+    rtems_status_code (*set_pin_mode)(rtems_gpio *, rtems_gpio_pin_mode);
+
+    /**
+      * @brief Handler for setting
+      *        pull resistor mode. 
+      *
+      * Pull resistor modes are from rtems_gpio_pull enumeration.
+      */
+    rtems_status_code (*set_pull)(rtems_gpio *, rtems_gpio_pull);
+
+    /**
+      * @brief Handler for configuring
+      *        interrupt of a pin. 
+      * 
+      * This handler should register ISR and its argument, interrupt
+      * trigger mode, and pull resister mode for the pin.
+      *
+      * @note Enabling interrupt should be done in enable_interrupt()
+      *       handler.
+      */
+    rtems_status_code (*configure_interrupt)(rtems_gpio *, rtems_gpio_isr, void *, rtems_gpio_interrupt_trig, rtems_gpio_pull);
+
+    /**
+      * @brief Handler for removing
+      *        interrupt settings of a pin. 
+      *
+      * Interrupt settings can be ISR address, pin configuration, etc.
+      */
+    rtems_status_code (*remove_interrupt)(rtems_gpio *);
+
+    /**
+      * @brief Handler for enabling
+      *        interrupt functionality of a pin.
+      */
+    rtems_status_code (*enable_interrupt)(rtems_gpio *);
+
+    /**
+      * @brief Handler for disabling
+      *        interrupt of a pin. 
+      */
+    rtems_status_code (*disable_interrupt)(rtems_gpio *);
+
+    /**
+      * @brief Handler for reading
+      *        the digital value of a pin. 
+      *
+      * The returned value should be in rtems_gpio_pin_state enum.
+      */
+    rtems_status_code (*read)(rtems_gpio *, rtems_gpio_pin_state *);
+
+    /**
+      * @brief Handler for writing 
+      *        a digital value to a pin. 
+      */
+    rtems_status_code (*write)(rtems_gpio *, rtems_gpio_pin_state);
+
+    /**
+      * @brief Handler for toggling
+      *        a pin. 
+      *
+      * It should change pin state from SET to RESET or vice versa.
+      */
+    rtems_status_code (*toggle)(rtems_gpio *);
+
+};
+
+/**
+  * @brief Structure representing a GPIO object. 
+  *
+  * Drivers need to define their own GPIO structures with
+  * rtems_gpio being the first member.
+  */
+struct rtems_gpio {
+    /**
+      * @brief The pin's virtual pin number
+      */
+    uint32_t virtual_pin;
+    /**
+      * @brief Handlers for this GPIO controller.
+      */
+    const rtems_gpio_handlers *gpio_handlers;
+};
+
+/** @} */
+
+/**
+  * @name GPIO System operations
+  *
+  * Functions in this group are mostly used by drivers to configure
+  * the GPIO system.
+  * @{
+  */
+
+/**
+  * @brief Registers a GPIO controller with GPIO manager.
+  *
+  * This function registers the pointer to driver-specific
+  * get_gpio() and destroy_gpio() functions. Those two functions
+  * are for creating and destroying GPIO objects. It also takes 
+  * the number of pins of each driver for mapping into a
+  * flat pin numbering system (virtual pin number).
+  * This function also help register peripherals API get()
+  * and remove() functions.
+  *
+  * @param get_gpio The pointer to driver-specific get_gpio()
+  * @param destroy_gpio The pointer to driver-specific 
+  *        destroy_gpio()
+  * @param get_api The pointer to driver-specific get_api()
+  * @param remove_api The pointer to driver-specific remove_api()
+  * @param pin_count The number of GPIO pins in the controller
+  *
+  * @retval RTEMS_SUCCESSFUL Controller registered successfully
+  * @retval RTEMS_TOO_MANY if the maximum number of controllers are
+  *         already registered
+  */
+extern rtems_status_code rtems_gpio_register(
+    rtems_status_code (*get_gpio)(uint32_t, rtems_gpio **),
+    rtems_status_code (*destroy_gpio)(rtems_gpio *),
+    uint32_t pin_count
+);
+
+/** @} */
+
+/**
+  * @name GPIO BSP functions
+  *
+  * BSP and drivers need to implement these.
+  *
+  * @{
+  */
+
+/** @} */
+
+/**
+  * @name GPIO Application operations
+  *
+  * @{
+  */
+
+/**
+  * @brief Get the GPIO object containing information
+  *        about the specified pin.
+  * 
+  * This function maps the virtual pin to intermediate pin, 
+  * and pass to the driver-specific function to get a
+  * GPIO object.
+  *
+  * @note Warning: this function may use malloc(). When you 
+  * are done with the GPIO object, call rtems_gpio_destroy()
+  * to avoid memory leak.
+  *
+  * @param virt_pin The virtual pin number.
+  * @param[out] out The pointer to the pointer to the output
+  *             GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  * @retval RTEMS_UNSTISFIED if the virtual pin number
+  *         is invalid (i.e. out of range)
+  */
+extern rtems_status_code rtems_gpio_get(
+    uint32_t virt_pin,
+    rtems_gpio **out
+);
+
+/**
+  * @brief Destroy a GPIO object
+  *
+  * This function should be called on an GPIO object which is
+  * no longer used to avoid memory leak. Internally it can 
+  * use free().
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  * @retval RTEMS_UNSATISFIED
+  */
+extern rtems_status_code rtems_gpio_destroy(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Sets the pin mode of a pin.
+  *
+  * This function calls the registered driver-specific handler.
+  * It can be used to set the pin mode for a pin. 
+  *
+  * @param[in] base The GPIO object to be configured.
+  * @param mode The pin mode from the enumeration rtems_gpio_pin_mode
+  *
+  * @retval RTEMS_SUCCESSFUL GPIO configured successfully.
+  * @retval RTEMS_UNSATISFIED Could not set the pin mode.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_set_pin_mode(
+    rtems_gpio *base, 
+    rtems_gpio_pin_mode mode
+);
+
+/**
+  * @brief Sets the pin's pull resistor configuration.
+  *
+  * This function calls the registered driver-specific handler.
+  * It can be used to set the pull resistor mode for a pin.
+  *
+  * @param[in] base The GPIO object to be configured.
+  * @param mode The pull mode from the enumeration rtems_gpio_pull
+  *
+  * @retval RTEMS_SUCCESSFUL GPIO configured successfully.
+  * @retval RTEMS_UNSATISFIED Could not set the pull resistor mode.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_set_pull(
+    rtems_gpio *base, 
+    rtems_gpio_pull pull
+);
+
+/**
+  * @brief Configure interrupt on a GPIO pin.
+  *
+  * This function calls the registered driver-specific handler.
+  * It can be used to set up a pin for interrupt mode.
+  *
+  * @note This only configures the interrupt but not enable it. Use
+  *       rtems_gpio_enable_interrupt() to actually enable interrupt.
+  *
+  * @param[in] base The GPIO object to be configured.
+  * @param isr The pointer to the ISR to be attached to this pin.
+  * @param[in] arg The pointer to the argument of the ISR.
+  * @param trig The trigger mode
+  * @param pull The pull resistor mode
+  *
+  * @retval RTEMS_SUCCESSFUL Interrupt configured successfully.
+  * @retval RTEMS_UNSATISFIED Could not configure interrupt.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_configure_interrupt(
+    rtems_gpio *base, 
+    rtems_gpio_isr isr,
+    void *arg,
+    rtems_gpio_interrupt_trig trig,
+    rtems_gpio_pull pull
+);
+
+/**
+  * @brief Remove interrupt settings for a pin.
+  *
+  * This function calls the registered driver-specific handler.
+  * It can be used to remove interrupt configuration of a pin like
+  * ISR, ISR argument, pin mode, etc.
+  *
+  * @note This only removes the interrupt but not disable it. Use
+  *       rtems_gpio_disable_interrupt() to actually disable 
+  *       interrupt.
+  *
+  * @param[in] base The GPIO object to be configured.
+  *
+  * @retval RTEMS_SUCCESSFUL Interrupt removed successfully.
+  * @retval RTEMS_UNSATISFIED Could not remove interrupt.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_remove_interrupt(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Enable interrupt on a GPIO pin.
+  *
+  * This function calls the registered driver-specific handler.
+  *
+  * @note This function only enables the interrupt (e.g. the vector)
+  *       but not configure the pin. Use 
+  *       rtems_gpio_configure_interrupt() for pin configuration.
+  *
+  * @param[in] base The GPIO object to be configured.
+  *
+  * @retval RTEMS_SUCCESSFUL Interrupt enabled successfully.
+  * @retval RTEMS_UNSATISFIED Could not enable interrupt.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_enable_interrupt(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Disable interrupt on a GPIO pin.
+  *
+  * This function calls the registered driver-specific handler.
+  *
+  * @note This function only disables the interrupt (e.g. the vector)
+  *       but not remove the pin's configurations. Use 
+  *       rtems_gpio_remove_interrupt() for the latter purpose.
+  *
+  * @param[in] base The GPIO object to be configured.
+  *
+  * @retval RTEMS_SUCCESSFUL Interrupt disabled successfully.
+  * @retval RTEMS_UNSATISFIED Could not disable interrupt.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_disable_interrupt(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Writes a digital value to a pin. 
+  *
+  * This function calls the registered driver-specific handler.
+  *
+  * @param[in] base The GPIO object that has information about the
+  *                  pin.
+  * @param value The state to be written to the pin.
+  *
+  * @retval RTEMS_SUCCESSFUL Pin successfully written.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_write(
+    rtems_gpio *base, 
+    rtems_gpio_pin_state value
+);
+
+/**
+  * @brief Reads the digital value of a pin. 
+  *
+  * This function calls the registered driver-specific handler.
+  *
+  * @param[in] base The GPIO object that has information about the
+  *                  pin.
+  *
+  * @param[out] value The state of the pin.
+  *
+  * @retval RTEMS_SUCCESSFUL Pin succesfully read.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_read(
+    rtems_gpio *base, 
+    rtems_gpio_pin_state *value
+);
+
+/**
+  * @brief Toggles the state of a GPIO pin.
+  *
+  * This function calls the registered driver-specific handler.
+  *
+  * @param[in] base The GPIO object that has information about the
+  *                  pin.
+  *
+  * @retval RTEMS_SUCCESSFUL Pin successfully toggled.
+  * @retval See driver-specific function for other return codes.
+  */
+extern rtems_status_code rtems_gpio_toggle(
+    rtems_gpio *base
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_BSP_GPIO2_H */
diff --git a/bsps/shared/dev/gpio/gpio2.c b/bsps/shared/dev/gpio/gpio2.c
new file mode 100644
index 0000000000..94a0859454
--- /dev/null
+++ b/bsps/shared/dev/gpio/gpio2.c
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+  * @file
+  *
+  * @ingroup gpio2
+  */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/gpio2.h>
+#include <rtems/sysinit.h>
+
+/**
+  * @brief An array to store all registered GPIO controllers.
+  */
+static rtems_status_code (*get_gpio_table[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS])(uint32_t, rtems_gpio **);
+
+/**
+  * @brief An array to store all registered GPIO controllers.
+  */
+static rtems_status_code (*destroy_gpio_table[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS])(rtems_gpio *);
+
+/**
+  * @brief An array to store the boundaries of pin index of 
+  *        GPIO controllers.
+  *
+  * Example with 2 16-pin controllers and 1 32-pin controller,
+  * the pin_map will be:
+  * { 0, 16, 32, 64}
+  * Value 0 is always at index 0 for convenience of calculation.
+  * The length of this array is always 1+(number of controllers).
+  */
+static uint32_t pin_map[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS+1] = {0};
+
+/**
+  * @brief The number of controllers registered.
+  */
+static uint32_t num_ctrl = 0;
+
+static uint32_t get_ctrl_index(
+    uint32_t virtual_pin
+)
+{
+    uint32_t i;
+    for (i = 1; i <= num_ctrl; ++i) {
+        if (virtual_pin < pin_map[i]) {
+            break;
+        }
+    }
+    return i-1;
+}
+
+rtems_status_code rtems_gpio_register(
+    rtems_status_code (*get_gpio)(uint32_t, rtems_gpio **),
+    rtems_status_code (*destroy_gpio)(rtems_gpio *),
+    uint32_t pin_count
+) 
+{
+    rtems_interrupt_level level;
+
+    if (num_ctrl == CONFIGURE_GPIO_MAXIMUM_CONTROLLERS)
+        return RTEMS_TOO_MANY;
+
+    rtems_interrupt_disable(level);
+    get_gpio_table[num_ctrl] = get_gpio;
+    destroy_gpio_table[num_ctrl] = destroy_gpio;
+
+    pin_map[num_ctrl+1] = pin_map[num_ctrl] + pin_count;
+    ++num_ctrl;
+    rtems_interrupt_enable(level);
+
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_get(
+    uint32_t virt_pin,
+    rtems_gpio **out
+) 
+{
+    uint32_t i = get_ctrl_index(virt_pin);
+    if (i >= num_ctrl)
+        return RTEMS_UNSATISFIED;
+
+    uint32_t pin = virt_pin - pin_map[i];
+    rtems_status_code sc = (*get_gpio_table[i])(pin, out);
+    if (sc == RTEMS_SUCCESSFUL) {
+        (*out)->virtual_pin = virt_pin;
+    }
+    return sc;
+}
+
+rtems_status_code rtems_gpio_destroy(
+    rtems_gpio *base
+)
+{
+    uint32_t i = get_ctrl_index(base->virtual_pin);
+    if (i >= num_ctrl)
+        return RTEMS_UNSATISFIED;
+    return (*destroy_gpio_table[i])(base);
+}
+
+rtems_status_code rtems_gpio_set_pin_mode(
+    rtems_gpio *base, 
+    rtems_gpio_pin_mode mode
+) 
+{
+    return base->gpio_handlers->set_pin_mode(base, mode);
+}
+
+rtems_status_code rtems_gpio_set_pull(
+    rtems_gpio *base, 
+    rtems_gpio_pull pull
+) 
+{
+    return base->gpio_handlers->set_pull(base, pull);
+}
+
+rtems_status_code rtems_gpio_configure_interrupt(
+    rtems_gpio *base, 
+    rtems_gpio_isr isr,
+    void *arg,
+    rtems_gpio_interrupt_trig trig,
+    rtems_gpio_pull pull
+) 
+{
+    return base->gpio_handlers->configure_interrupt(base, isr, arg, trig, pull);
+}
+
+rtems_status_code rtems_gpio_remove_interrupt(
+    rtems_gpio *base
+)
+{
+    return base->gpio_handlers->remove_interrupt(base);
+}
+
+rtems_status_code rtems_gpio_enable_interrupt(
+    rtems_gpio *base
+)
+{
+    return base->gpio_handlers->enable_interrupt(base);
+}
+
+rtems_status_code rtems_gpio_disable_interrupt(
+    rtems_gpio *base
+)
+{
+    return base->gpio_handlers->disable_interrupt(base);
+}
+
+rtems_status_code rtems_gpio_write(
+    rtems_gpio *base, 
+    rtems_gpio_pin_state value
+) 
+{
+    return base->gpio_handlers->write(base, value);
+}
+
+rtems_status_code rtems_gpio_read(
+    rtems_gpio *base, 
+    rtems_gpio_pin_state *value
+) 
+{
+    return base->gpio_handlers->read(base, value);
+}
+
+rtems_status_code rtems_gpio_toggle(
+    rtems_gpio *base
+) 
+{
+    return base->gpio_handlers->toggle(base);
+}
+
+static void rtems_gpio_start(
+    void
+)
+{
+    *gpio_dummy = 1;
+}
+RTEMS_SYSINIT_ITEM(
+    rtems_gpio_start,
+    RTEMS_SYSINIT_BSP_START,
+    RTEMS_SYSINIT_ORDER_LAST
+);
diff --git a/spec/build/bsps/bspopts.yml b/spec/build/bsps/bspopts.yml
index 4a4c06d321..d0e31e8ae1 100644
--- a/spec/build/bsps/bspopts.yml
+++ b/spec/build/bsps/bspopts.yml
@@ -7,6 +7,8 @@ guard: __BSP_OPTIONS_H
 include-headers: []
 install-path: ${BSP_INCLUDEDIR}
 links:
+- role: build-dependency
+  uid: optmaxnumgpio
 - role: build-dependency
   uid: optbspoptflags
 - role: build-dependency
diff --git a/spec/build/bsps/obj.yml b/spec/build/bsps/obj.yml
index ebe0e0bbce..4de7bf6d16 100644
--- a/spec/build/bsps/obj.yml
+++ b/spec/build/bsps/obj.yml
@@ -16,7 +16,7 @@ install:
   - bsps/include/bsp/default-initial-extension.h
   - bsps/include/bsp/fatal.h
   - bsps/include/bsp/fdt.h
-  - bsps/include/bsp/gpio.h
+  - bsps/include/bsp/gpio2.h
   - bsps/include/bsp/irq-default.h
   - bsps/include/bsp/irq-generic.h
   - bsps/include/bsp/irq-info.h
diff --git a/spec/build/bsps/optmaxnumgpio.yml b/spec/build/bsps/optmaxnumgpio.yml
new file mode 100644
index 0000000000..5db4253e89
--- /dev/null
+++ b/spec/build/bsps/optmaxnumgpio.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-integer: null
+- define-condition: null
+build-type: option
+copyrights:
+- Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+default: 0
+default-by-variant: []
+description: |
+  The number of GPIO controllers used for this application.
+enabled-by: true
+format: '{}'
+links: []
+name: CONFIGURE_GPIO_MAXIMUM_CONTROLLERS
+type: build
-- 
2.37.1



More information about the devel mailing list