[PATCH v6 08/10] bsps/arm/stm32f4: GPIO Implementation

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


---
 bsps/arm/stm32f4/gpio/gpio.c                  | 557 ++++++++++++++++++
 bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h   | 281 +++++++++
 spec/build/bsps/arm/stm32f4/grp.yml           |   6 +-
 spec/build/bsps/arm/stm32f4/obj.yml           |   4 +
 .../build/bsps/arm/stm32f4/optnumgpioctrl.yml |  16 +
 5 files changed, 862 insertions(+), 2 deletions(-)
 create mode 100644 bsps/arm/stm32f4/gpio/gpio.c
 create mode 100644 bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
 create mode 100644 spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml

diff --git a/bsps/arm/stm32f4/gpio/gpio.c b/bsps/arm/stm32f4/gpio/gpio.c
new file mode 100644
index 0000000000..34b1d62cc0
--- /dev/null
+++ b/bsps/arm/stm32f4/gpio/gpio.c
@@ -0,0 +1,557 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+  * @file
+  *
+  * @ingroup stm32f4_gpio
+  */
+
+/*
+ * 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.h>
+#include <rtems.h>
+#include <stdlib.h>
+#include <bsp/stm32f4_gpio.h>
+#include <rtems/sysinit.h>
+
+/*********** GPIO API ***************/
+static rtems_status_code stm32f4_gpio_get(
+    uint32_t interm_pin,
+    rtems_gpio **out
+);
+
+static rtems_status_code stm32f4_gpio_destroy(
+    rtems_gpio *base
+);
+
+/*********************************************************/
+
+/**
+  * @brief STM32F4 GPIO handlers
+  */
+static const rtems_gpio_handlers stm32f4_gpio_handlers = {
+    .set_pin_mode = stm32f4_gpio_set_pin_mode,
+    .set_pull = stm32f4_gpio_set_pull,
+    .configure_interrupt = stm32f4_gpio_configure_interrupt,
+    .remove_interrupt = stm32f4_gpio_remove_interrupt,
+    .enable_interrupt = stm32f4_gpio_enable_interrupt,
+    .disable_interrupt = stm32f4_gpio_disable_interrupt,
+    .read = stm32f4_gpio_read,
+    .write = stm32f4_gpio_write,
+    .toggle = stm32f4_gpio_toggle
+};
+
+static GPIO_TypeDef * const GPIOx[] = {
+#ifdef GPIOA_BASE
+    GPIOA
+#endif /* GPIOA_BASE */
+#ifdef GPIOB_BASE
+    , GPIOB
+#endif /* GPIOB_BASE */
+#ifdef GPIOC_BASE
+    , GPIOC
+#endif /* GPIOC_BASE */
+#ifdef GPIOD_BASE
+    , GPIOD
+#endif /* GPIOD_BASE */
+#ifdef GPIOE_BASE
+    , GPIOE
+#endif /* GPIOE_BASE */
+#ifdef GPIOF_BASE
+    , GPIOF
+#endif /* GPIOF_BASE */
+#ifdef GPIOG_BASE
+    , GPIOG
+#endif /* GPIOG_BASE */
+#ifdef GPIOH_BASE
+    , GPIOH
+#endif /* GPIOH_BASE */
+#ifdef GPIOI_BASE
+    , GPIOI
+#endif /* GPIOI_BASE */
+#ifdef GPIOJ_BASE
+    , GPIOJ
+#endif /* GPIOJ_BASE */
+#ifdef GPIOK_BASE
+    , GPIOK
+#endif /* GPIOK_BASE */
+};
+
+static unsigned int const EXTIx_IRQn[] = {
+    EXTI0_IRQn,
+    EXTI1_IRQn,
+    EXTI2_IRQn,
+    EXTI3_IRQn,
+    EXTI4_IRQn,
+    EXTI9_5_IRQn,
+    EXTI9_5_IRQn,
+    EXTI9_5_IRQn,
+    EXTI9_5_IRQn,
+    EXTI9_5_IRQn,
+    EXTI15_10_IRQn,
+    EXTI15_10_IRQn,
+    EXTI15_10_IRQn,
+    EXTI15_10_IRQn,
+    EXTI15_10_IRQn,
+    EXTI15_10_IRQn
+};
+
+/**
+  * @brief Converts intermediate pin number to port pointer.
+  *
+  * Intermediate pin number is a way of numerically labeling
+  * pins. Pins are labeled incrementally across all ports.
+  * Pins 0-15 from port A are 0-15. Pins 0-15 from port B are
+  * 16-31. And so on.
+  *
+  * @param interm_pin is the intermediate pin number
+  */
+#define STM32F4_GET_PORT(interm_pin) (GPIOx[ ( interm_pin ) / 16 ])
+
+/**
+  * @brief Converts intermediate pin number to 0-15.
+  *
+  * Intermediate pin number is a way of numerically labeling
+  * pins. Pins are labeled incrementally across all ports.
+  * Pins 0-15 from port A are 0-15. Pins 0-15 from port B are
+  * 16-31. And so on.
+  *
+  * @param interm_pin is the intermediate pin number
+  */
+#define STM32F4_GET_PIN_0_15(interm_pin) (( interm_pin ) % 16) 
+
+/**
+  * @brief Converts pin number from 0-15 to HAL pin mask.
+  * @param pin is the pin number from 0-15
+  */
+#define STM32F4_GET_HAL_GPIO_PIN(pin) ((uint16_t) (1 << ( pin )))
+
+/**
+  * @brief Get EXTI Line from pin number 0-15
+  * @param pin is the pin number from 0-15
+  */
+#define STM32F4_GET_LL_EXTI_LINE(pin) (0x1UL << ( pin ))
+
+/**
+  * @brief Get EXTI IRQ number from pin 0-15
+  * @param pin is the pin number from 0-15
+  */
+#define STM32F4_GET_EXTI_IRQn(pin) (EXTIx_IRQn[( pin )])
+
+/************** Interrupt manager *****************/
+typedef struct {
+    void *arg;
+    stm32f4_gpio *gpio;
+} stm32f4_interrupt_arg;
+
+typedef struct {
+    stm32f4_interrupt_arg arg;
+    rtems_gpio_isr isr;
+} stm32f4_interrupt;
+
+static stm32f4_interrupt isr_table[16]; 
+static bool isr_registered[16] = {0};
+
+void exti_handler(void *arg);
+
+
+/********** STM32F4 GPIO API functions ************/
+
+/**
+  * @brief Register integrated GPIO controller.
+  */
+static void stm32f4_gpio_register_controllers(
+    void
+)
+{
+    rtems_gpio_register(
+            stm32f4_gpio_get,
+            stm32f4_gpio_destroy,
+            sizeof(GPIOx)/sizeof(GPIOx[0])*16
+    );
+}
+
+rtems_status_code stm32f4_gpio_get(
+    uint32_t interm_pin,
+    rtems_gpio **out
+)
+{
+    stm32f4_gpio *tmp = malloc(sizeof(stm32f4_gpio));
+    if (tmp == NULL) {
+        return RTEMS_NO_MEMORY;
+    }
+    tmp->base = RTEMS_GPIO_BUILD_BASE(&stm32f4_gpio_handlers);
+    tmp->pin = STM32F4_GET_PIN_0_15(interm_pin);
+    tmp->port = STM32F4_GET_PORT(interm_pin);
+    
+    // initialize the pin
+    stm32f4_gpio_init((rtems_gpio *) tmp);
+
+    *out = (rtems_gpio *) tmp;
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_destroy(
+    rtems_gpio *base
+)
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    free(gpio);
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_set_pin_mode(
+    rtems_gpio *base, 
+    rtems_gpio_pin_mode mode
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(gpio->pin);
+
+    uint32_t stm32f4_mode, stm32f4_output_type;
+    switch (mode) {
+    case RTEMS_GPIO_PINMODE_OUTPUT_PP:
+        stm32f4_mode = LL_GPIO_MODE_OUTPUT;
+        stm32f4_output_type = LL_GPIO_OUTPUT_PUSHPULL;
+        break;
+    case RTEMS_GPIO_PINMODE_OUTPUT_OD:
+        stm32f4_mode = LL_GPIO_MODE_OUTPUT;
+        stm32f4_output_type = LL_GPIO_OUTPUT_OPENDRAIN;
+        break;
+    case RTEMS_GPIO_PINMODE_INPUT:
+        stm32f4_mode = LL_GPIO_MODE_INPUT;
+        break;
+    case RTEMS_GPIO_PINMODE_ANALOG:
+        stm32f4_mode = LL_GPIO_MODE_ANALOG;
+        break;
+    case RTEMS_GPIO_PINMODE_BSP_SPECIFIC:
+        stm32f4_mode = LL_GPIO_MODE_ALTERNATE;
+        break;
+    default:
+        /* illegal argument */
+        return RTEMS_UNSATISFIED;
+    }
+    LL_GPIO_SetPinMode(gpio->port, pin_mask, stm32f4_mode);
+    if (stm32f4_mode == LL_GPIO_MODE_OUTPUT) {
+        LL_GPIO_SetPinOutputType(gpio->port, pin_mask, stm32f4_output_type);
+    }
+
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_set_pull(
+    rtems_gpio *base, 
+    rtems_gpio_pull pull
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(gpio->pin);
+    uint32_t stm32f4_pull;
+
+    switch (pull) {
+    case RTEMS_GPIO_NOPULL:
+        stm32f4_pull = LL_GPIO_PULL_NO;
+        break;
+    case RTEMS_GPIO_PULLUP:
+        stm32f4_pull = LL_GPIO_PULL_UP;
+        break;
+    case RTEMS_GPIO_PULLDOWN:
+        stm32f4_pull = LL_GPIO_PULL_DOWN;
+        break;
+    default:
+        /* Illegal argument */
+        return RTEMS_UNSATISFIED;
+    }
+    LL_GPIO_SetPinPull(gpio->port, pin_mask, stm32f4_pull);
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_configure_interrupt(
+    rtems_gpio *base, 
+    rtems_gpio_isr isr,
+    void *arg,
+    rtems_gpio_interrupt_trig trig,
+    rtems_gpio_pull pull
+) 
+{
+    // configure pin
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(gpio->pin);
+    GPIO_InitTypeDef hal_conf;
+
+    switch (trig) {
+    case RTEMS_GPIO_INT_TRIG_NONE:
+        return RTEMS_SUCCESSFUL;
+    case RTEMS_GPIO_INT_TRIG_FALLING:
+        hal_conf.Mode = GPIO_MODE_IT_FALLING;
+        break;
+    case RTEMS_GPIO_INT_TRIG_RISING:
+        hal_conf.Mode = GPIO_MODE_IT_RISING;
+        break;
+    case RTEMS_GPIO_INT_TRIG_BOTH_EDGES:
+        hal_conf.Mode = GPIO_MODE_IT_RISING_FALLING;
+        break;
+    default:
+        /* Invalid argument */
+        return RTEMS_UNSATISFIED;
+    }
+    switch (pull) {
+    case RTEMS_GPIO_NOPULL:
+        hal_conf.Pull = GPIO_NOPULL;
+        break;
+    case RTEMS_GPIO_PULLUP:
+        hal_conf.Pull = GPIO_PULLUP;
+        break;
+    case RTEMS_GPIO_PULLDOWN:
+        hal_conf.Pull = GPIO_PULLDOWN;
+        break;
+    default:
+        /* Illegal argument */
+        return RTEMS_UNSATISFIED;
+    }
+    hal_conf.Pin = pin_mask;
+    HAL_GPIO_Init(gpio->port, &hal_conf);
+
+    // RTEMS interrupt config
+    if (isr_registered[gpio->pin]) {
+        return RTEMS_UNSATISFIED;
+    }
+    isr_table[gpio->pin] = (stm32f4_interrupt){
+        .arg = {
+            .arg = arg,
+            .gpio = gpio
+        },
+        .isr = isr
+    };
+    isr_registered[gpio->pin] = true;
+    rtems_option opt = gpio->pin < 5 ? 
+                        RTEMS_INTERRUPT_UNIQUE : 
+                        RTEMS_INTERRUPT_SHARED;
+    rtems_status_code sc = rtems_interrupt_handler_install(
+            STM32F4_GET_EXTI_IRQn(gpio->pin), 
+            NULL, 
+            opt, 
+            exti_handler, 
+            &isr_table[gpio->pin].arg
+    );
+
+    return sc;
+}
+
+rtems_status_code stm32f4_gpio_remove_interrupt(
+    rtems_gpio *base
+)
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    if (isr_registered[gpio->pin]) {
+        rtems_status_code sc = rtems_interrupt_handler_remove(
+                STM32F4_GET_EXTI_IRQn(gpio->pin), 
+                exti_handler, 
+                &isr_table[gpio->pin].arg
+        );
+        if (sc == RTEMS_SUCCESSFUL) {
+            isr_registered[gpio->pin] = false;
+        }
+        return sc;
+    }
+    return RTEMS_UNSATISFIED;
+}
+
+rtems_status_code stm32f4_gpio_enable_interrupt(
+    rtems_gpio *base
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    LL_EXTI_EnableIT_0_31(STM32F4_GET_LL_EXTI_LINE(gpio->pin));
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_disable_interrupt(
+    rtems_gpio *base
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    LL_EXTI_DisableIT_0_31(STM32F4_GET_LL_EXTI_LINE(gpio->pin));
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_write(
+    rtems_gpio *base, 
+    rtems_gpio_pin_state value
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+    if (value)
+        LL_GPIO_SetOutputPin(gpio->port, STM32F4_GET_HAL_GPIO_PIN(gpio->pin));
+    else
+        LL_GPIO_ResetOutputPin(gpio->port, STM32F4_GET_HAL_GPIO_PIN(gpio->pin));
+
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_read(
+    rtems_gpio *base, 
+    rtems_gpio_pin_state *value
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+    *value = LL_GPIO_IsInputPinSet(
+            gpio->port, 
+            STM32F4_GET_HAL_GPIO_PIN(gpio->pin)
+    );
+    return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_toggle(
+    rtems_gpio *base
+) 
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+    LL_GPIO_TogglePin(
+            gpio->port, 
+            STM32F4_GET_HAL_GPIO_PIN(gpio->pin)
+    );
+    return RTEMS_SUCCESSFUL;
+}
+
+void exti_handler(void *arg) {
+    stm32f4_interrupt_arg *stm32_arg = (stm32f4_interrupt_arg *) arg;
+    uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(stm32_arg->gpio->pin);
+    if(__HAL_GPIO_EXTI_GET_IT(pin_mask) != RESET)
+    {
+        __HAL_GPIO_EXTI_CLEAR_IT(pin_mask);
+        (*isr_table[stm32_arg->gpio->pin].isr)(stm32_arg->arg);
+    }
+}
+
+/************ STM32F4 Other specific GPIO functions ************/
+rtems_status_code stm32f4_gpio_init(rtems_gpio *base) {
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    
+    switch ((uintptr_t) gpio->port) {
+#ifdef GPIOA_BASE
+        case (uintptr_t) GPIOA:
+            __HAL_RCC_GPIOA_CLK_ENABLE();
+            break;
+#endif /* GPIOA_BASE */
+#ifdef GPIOB_BASE
+        case (uintptr_t) GPIOB:
+            __HAL_RCC_GPIOB_CLK_ENABLE();
+            break;
+#endif /* GPIOB_BASE */
+#ifdef GPIOC_BASE
+        case (uintptr_t) GPIOC:
+            __HAL_RCC_GPIOC_CLK_ENABLE();
+            break;
+#endif /* GPIOC_BASE */
+#ifdef GPIOD_BASE
+        case (uintptr_t) GPIOD:
+            __HAL_RCC_GPIOD_CLK_ENABLE();
+            break;
+#endif /* GPIOD_BASE */
+#ifdef GPIOE_BASE
+        case (uintptr_t) GPIOE:
+            __HAL_RCC_GPIOE_CLK_ENABLE();
+            break;
+#endif /* GPIOE_BASE */
+#ifdef GPIOF_BASE
+        case (uintptr_t) GPIOF:
+            __HAL_RCC_GPIOF_CLK_ENABLE();
+            break;
+#endif /* GPIOF_BASE */
+#ifdef GPIOG_BASE
+        case (uintptr_t) GPIOG:
+            __HAL_RCC_GPIOG_CLK_ENABLE();
+            break;
+#endif /* GPIOG_BASE */
+#ifdef GPIOH_BASE
+        case (uintptr_t) GPIOH:
+            __HAL_RCC_GPIOH_CLK_ENABLE();
+            break;
+#endif /* GPIOH_BASE */
+#ifdef GPIOI_BASE
+        case (uintptr_t) GPIOI:
+            __HAL_RCC_GPIOI_CLK_ENABLE();
+            break;
+#endif /* GPIOI_BASE */
+#ifdef GPIOJ_BASE
+        case (uintptr_t) GPIOJ:
+            __HAL_RCC_GPIOJ_CLK_ENABLE();
+            break;
+#endif /* GPIOJ_BASE */
+#ifdef GPIOK_BASE
+        case (uintptr_t) GPIOK:
+            __HAL_RCC_GPIOK_CLK_ENABLE();
+            break;
+#endif /* GPIOK_BASE */
+        default:
+            return RTEMS_UNSATISFIED;
+    }
+    return RTEMS_SUCCESSFUL;
+}
+
+void stm32f4_gpio_lock_pin(
+    rtems_gpio *base
+)
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    LL_GPIO_LockPin(
+            gpio->port,
+            STM32F4_GET_HAL_GPIO_PIN(gpio->pin)
+    );
+}
+
+void stm32f4_gpio_set_af(
+    rtems_gpio *base,
+    uint32_t alternate
+)
+{
+    stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+    if (gpio->pin < 8)
+        LL_GPIO_SetAFPin_0_7(
+                gpio->port,
+                STM32F4_GET_HAL_GPIO_PIN(gpio->pin),
+                alternate
+        );
+    else
+        LL_GPIO_SetAFPin_8_15(
+                gpio->port,
+                STM32F4_GET_HAL_GPIO_PIN(gpio->pin),
+                alternate
+        );
+}
+
+RTEMS_GPIO_LINK();
+
+RTEMS_SYSINIT_ITEM(
+    stm32f4_gpio_register_controllers,
+    RTEMS_SYSINIT_BSP_PRE_DRIVERS,
+    RTEMS_SYSINIT_ORDER_LAST_BUT_1
+);
+
diff --git a/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h b/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
new file mode 100644
index 0000000000..27dcd75751
--- /dev/null
+++ b/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
@@ -0,0 +1,281 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+  * @file
+  * 
+  * @ingroup stm32f4_gpio
+  *
+  * STM32F4 BSP implementation of GPIO.
+  */
+
+/*
+ * 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_ARM_STM32F4_BSP_GPIO
+#define LIBBSP_ARM_STM32F4_BSP_GPIO
+
+#include <stdbool.h>
+#include <stm32f4xx.h>
+#include <stm32f4xx_ll_gpio.h>
+#include <stm32f4xx_ll_exti.h>
+#include <bsp/gpio2.h>
+
+/*********** Helpers *****************/
+/**
+  * @brief Macro to get stm32f4_gpio object from a base rtems_gpio
+  *        object.
+  * 
+  * This is a wrapper of RTEMS_CONTAINER_OF macro
+  *
+  * @param base The pointer to a rtems_gpio object
+  * @retval The pointer to the stm32f4_gpio object owning
+  *         the specified rtems_gpio object
+  */
+#define stm32f4_get_gpio_from_base(_base) \
+    RTEMS_CONTAINER_OF(_base, stm32f4_gpio, base)
+
+/**
+  * @brief STM32F4 BSP GPIO structure
+  *
+  */
+typedef struct {
+    /**
+      * @brief This member is a rtems_gpio object.
+      */
+    rtems_gpio base;
+    /**
+      *@brief This member is the pin number from 0 to 15.
+      */
+    uint32_t pin;
+    /**
+      * @brief This member is HAL GPIOx pointer.
+      */
+    GPIO_TypeDef *port;
+} stm32f4_gpio;
+
+/**
+  * @name STM32F4 GPIO functions
+  *
+  * @{
+  */
+
+/**
+  * @name GPIO API implementation of STM32F4 BSP
+  *
+  * @{
+  */
+
+
+/**
+  * @brief Sets the pin mode.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  * @param mode is a value of @see rtems_gpio_pin_mode
+  *
+  * @retval RTEMS_SUCCESSFUL if the pin mode is valid.
+  * @retval RTEMS_UNSATISFIED if the pin mode is 
+  *         invalid.
+  */
+extern rtems_status_code stm32f4_gpio_set_pin_mode(
+    rtems_gpio *base,
+    rtems_gpio_pin_mode mode
+);
+
+/**
+  * @brief Sets pull resistor mode.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  * @param pull is a value of @see rtems_gpio_pull
+  *
+  * @retval RTEMS_SUCCESSFUL if the pull resistor 
+  *         mode is valid.
+  * @retval RTEMS_UNSATISFIED if the pull resistor
+  *         mode is invalid.
+  */
+extern rtems_status_code stm32f4_gpio_set_pull(
+    rtems_gpio *base,
+    rtems_gpio_pull pull
+);
+
+/**
+  * @brief Configures user-defined ISR for an EXTI.
+  *
+  * This function is used to register a custom ISR
+  * with a GPIO pin. This API supports up to 1 ISR
+  * for each EXTI line (total 16 ISRs) at a time.
+  * 
+  * @note If there is already an ISR registered with 
+  *       a line, it needs to be removed to be able
+  *       to register a new one.
+  * @note This function does not enable interrupt.
+  *       use @see rtems_gpio_enable_interrupt().
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL if interrupt 
+  *         configuration is successful.
+  * @retval RTEMS_UNSATISFIED if trigger mode/pull
+  *         resistor mode is invalid or an ISR
+  *         has already been registered for this 
+  *         EXTI line.
+  * @retval @see rtems_interrupt_handler_install()
+  */
+extern rtems_status_code stm32f4_gpio_configure_interrupt(
+    rtems_gpio *base, 
+    rtems_gpio_isr isr,
+    void *arg,
+    rtems_gpio_interrupt_trig trig,
+    rtems_gpio_pull pull
+);
+
+/**
+  * @brief Removes the registered ISR.
+  *
+  * @note This function does not disable interrupt.
+  * @ref rtems_gpio_disable_interrupt()
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL if ISR removed successfully.
+  * @retval RTEMS_UNSATISFIED if no ISR registered for 
+  *         selected line.
+  * @retval @see rtems_interrupt_handler_remove()
+  */
+extern rtems_status_code stm32f4_gpio_remove_interrupt(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Enables EXTI for the line connected to this
+  *        pin.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  */
+extern rtems_status_code stm32f4_gpio_enable_interrupt(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Disables EXTI for the line connected to 
+  *        this pin.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  */
+extern rtems_status_code stm32f4_gpio_disable_interrupt(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Reads digital value into a variable.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  * @param[out] value The pointer to the output
+  *             variable.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  */
+extern rtems_status_code stm32f4_gpio_read(
+    rtems_gpio *base,
+    rtems_gpio_pin_state *value
+);
+
+/**
+  * @brief Writes digital value to a pin.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  * @param value The output digital value.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  */
+extern rtems_status_code stm32f4_gpio_write(
+    rtems_gpio *base,
+    rtems_gpio_pin_state value
+);
+
+/**
+  * @brief Toggles the state of a pin.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL
+  */
+extern rtems_status_code stm32f4_gpio_toggle(
+    rtems_gpio *base
+);
+
+/** @} */
+
+/**
+  * @name Extra functionality of STM32F4 GPIO
+  *
+  * @{
+  */
+
+/**
+  * @brief Initializes clock for the GPIO port
+  *        owning this pin.
+  *
+  * @note This function is called in stm32f4_gpio_get().
+  *
+  * @param[in] base The pointer to the GPIO object.
+  *
+  * @retval RTEMS_SUCCESSFUL if the port argument is
+  *         valid
+  * @retval RTEMS_UNSATISFIED if the port argument is
+  *         invalid
+  */
+extern rtems_status_code stm32f4_gpio_init(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Lock configuration of a pin.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  */
+extern void stm32f4_gpio_lock_pin(
+    rtems_gpio *base
+);
+
+/**
+  * @brief Sets the alternate function for a pin.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  * @param alternate Alternate function, from 0-15.
+  */
+extern void stm32f4_gpio_set_af(
+    rtems_gpio *base,
+    uint32_t alternate
+);
+
+/** @} */
+
+/** @} */
+
+#endif /* LIBBSP_ARM_STM32F4_BSP_GPIO */
diff --git a/spec/build/bsps/arm/stm32f4/grp.yml b/spec/build/bsps/arm/stm32f4/grp.yml
index 99a78e1890..1cb14c7ae6 100644
--- a/spec/build/bsps/arm/stm32f4/grp.yml
+++ b/spec/build/bsps/arm/stm32f4/grp.yml
@@ -16,8 +16,6 @@ links:
   uid: ../start
 - role: build-dependency
   uid: abi
-- role: build-dependency
-  uid: obj
 - role: build-dependency
   uid: optenhal
 - role: build-dependency
@@ -26,6 +24,8 @@ links:
   uid: opthse
 - role: build-dependency
   uid: optusehse
+- role: build-dependency
+  uid: optnumgpioctrl
 - role: build-dependency
   uid: opteni2c1
 - role: build-dependency
@@ -66,6 +66,8 @@ links:
   uid: ../../objirq
 - role: build-dependency
   uid: ../../objmem
+- role: build-dependency
+  uid: obj
 - role: build-dependency
   uid: ../../bspopts
 type: build
diff --git a/spec/build/bsps/arm/stm32f4/obj.yml b/spec/build/bsps/arm/stm32f4/obj.yml
index 257ac48079..f05c072fec 100644
--- a/spec/build/bsps/arm/stm32f4/obj.yml
+++ b/spec/build/bsps/arm/stm32f4/obj.yml
@@ -152,6 +152,8 @@ install:
   - bsps/arm/stm32f4/include/bsp/stm32f10xxx_gpio.h
   - bsps/arm/stm32f4/include/bsp/stm32f10xxx_rcc.h
   - bsps/arm/stm32f4/include/bsp/stm32f4.h
+  - bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
+  - bsps/arm/stm32f4/include/bsp/stm32f4xxxx_adc.h
   - bsps/arm/stm32f4/include/bsp/stm32f4xxxx_exti.h
   - bsps/arm/stm32f4/include/bsp/stm32f4xxxx_flash.h
   - bsps/arm/stm32f4/include/bsp/stm32f4xxxx_gpio.h
@@ -259,6 +261,7 @@ source:
 - bsps/arm/stm32f4/hal/stm32f4xx_ll_usb.c
 - bsps/arm/stm32f4/hal/stm32f4xx_ll_utils.c
 - bsps/arm/stm32f4/hal/system_stm32f4xx.c
+- bsps/arm/stm32f4/gpio/gpio.c
 - bsps/arm/shared/irq/irq-armv7m.c
 - bsps/arm/shared/irq/irq-dispatch-armv7m.c
 - bsps/arm/shared/start/bsp-start-memcpy.S
@@ -273,6 +276,7 @@ source:
 - bsps/arm/stm32f4/start/rcc.c
 - bsps/arm/stm32f4/start/start-config-io.c
 - bsps/shared/cache/nocache.c
+- bsps/shared/dev/gpio/gpio2.c
 - bsps/shared/dev/btimer/btimer-cpucounter.c
 - bsps/shared/dev/cpucounter/cpucounterfrequency.c
 - bsps/shared/dev/cpucounter/cpucounterread.c
diff --git a/spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml b/spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml
new file mode 100644
index 0000000000..da21d9c62c
--- /dev/null
+++ b/spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-integer: null
+- define: null
+build-type: option
+copyrights:
+- Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+default: 1
+default-by-variant: []
+description: |
+  Number of GPIO controllers of this BSP.
+enabled-by: true
+format: '{}'
+links: []
+name: BSP_GPIO_NUM_CONTROLLERS
+type: build
-- 
2.37.1



More information about the devel mailing list