[PATCH v4 7/7] bsps/stm32f4: Fix GPIO port guards and ISR bug

Duc Doan dtbpkmte at gmail.com
Sat Jul 23 03:53:22 UTC 2022


Changes GPIO port guards from variant to #ifdef
of ports. Fixed ISR memory-leak bug. Changed GPIO
functions to extern and added comments for them.
---
 bsps/arm/stm32f4/gpio/gpio.c                | 182 ++++++++------------
 bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h | 167 ++++++++++++++++++
 2 files changed, 238 insertions(+), 111 deletions(-)

diff --git a/bsps/arm/stm32f4/gpio/gpio.c b/bsps/arm/stm32f4/gpio/gpio.c
index ac4d3b4f56..5bcff71b2d 100644
--- a/bsps/arm/stm32f4/gpio/gpio.c
+++ b/bsps/arm/stm32f4/gpio/gpio.c
@@ -54,58 +54,6 @@ static rtems_status_code stm32f4_gpio_destroy(
     rtems_gpio *base
 );
 
-static rtems_status_code stm32f4_gpio_init(
-    rtems_gpio *base
-);
-
-static rtems_status_code stm32f4_gpio_deinit(
-    rtems_gpio *base
-);
-
-static rtems_status_code stm32f4_gpio_set_pin_mode(
-    rtems_gpio *base,
-    rtems_gpio_pin_mode mode
-);
-
-static rtems_status_code stm32f4_gpio_set_pull(
-    rtems_gpio *base,
-    rtems_gpio_pull pull
-);
-
-static 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
-);
-
-static rtems_status_code stm32f4_gpio_remove_interrupt(
-    rtems_gpio *base
-);
-
-static rtems_status_code stm32f4_gpio_enable_interrupt(
-    rtems_gpio *base
-);
-
-static rtems_status_code stm32f4_gpio_disable_interrupt(
-    rtems_gpio *base
-);
-
-static rtems_status_code stm32f4_gpio_read(
-    rtems_gpio *base,
-    rtems_gpio_pin_state *value
-);
-
-static rtems_status_code stm32f4_gpio_write(
-    rtems_gpio *base,
-    rtems_gpio_pin_state value
-);
-
-static rtems_status_code stm32f4_gpio_toggle(
-    rtems_gpio *base
-);
-
 /*********************************************************/
 
 /**
@@ -126,11 +74,39 @@ static const rtems_gpio_handlers stm32f4_gpio_handlers = {
 };
 
 static GPIO_TypeDef * const GPIOx[] = {
-    GPIOA, GPIOB, GPIOC, GPIOD, GPIOE,
-    GPIOF, GPIOG, GPIOH, GPIOI,
-#ifdef STM32F429X
-    GPIOJ, GPIOK
-#endif /* STM32F429X */
+#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[] = {
@@ -206,6 +182,7 @@ typedef struct {
 } stm32f4_interrupt;
 
 static stm32f4_interrupt isr_table[16]; 
+static bool isr_registered[16] = {0};
 
 void exti_handler(void *arg);
 
@@ -253,41 +230,61 @@ rtems_status_code stm32f4_gpio_init(rtems_gpio *base) {
     stm32f4_gpio *gpio = 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;
-#ifdef STM32F429X
+#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 /* STM32F429X */
+#endif /* GPIOK_BASE */
         default:
             return RTEMS_UNSATISFIED;
     }
@@ -295,50 +292,6 @@ rtems_status_code stm32f4_gpio_init(rtems_gpio *base) {
 }
 
 rtems_status_code stm32f4_gpio_deinit(rtems_gpio *base) {
-/*
-    stm32f4_gpio *gpio = get_gpio_from_base(base);
-    
-    switch ((uintptr_t) gpio->port) {
-        case (uintptr_t) GPIOA:
-            __HAL_RCC_GPIOA_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOB:
-            __HAL_RCC_GPIOB_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOC:
-            __HAL_RCC_GPIOC_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOD:
-            __HAL_RCC_GPIOD_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOE:
-            __HAL_RCC_GPIOE_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOF:
-            __HAL_RCC_GPIOF_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOG:
-            __HAL_RCC_GPIOG_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOH:
-            __HAL_RCC_GPIOH_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOI:
-            __HAL_RCC_GPIOI_CLK_DISABLE();
-            break;
-#ifdef STM32F429X
-        case (uintptr_t) GPIOJ:
-            __HAL_RCC_GPIOJ_CLK_DISABLE();
-            break;
-        case (uintptr_t) GPIOK:
-            __HAL_RCC_GPIOK_CLK_DISABLE();
-            break;
-#endif 
-        default:
-            return RTEMS_UNSATISFIED;
-    }
-    return RTEMS_SUCCESSFUL;
-*/
     return RTEMS_NOT_IMPLEMENTED;
 }
 
@@ -455,6 +408,9 @@ rtems_status_code stm32f4_gpio_configure_interrupt(
     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,
@@ -462,6 +418,7 @@ rtems_status_code stm32f4_gpio_configure_interrupt(
         },
         .isr = isr
     };
+    isr_registered[gpio->pin] = true;
     rtems_option opt = gpio->pin < 5 ? 
                         RTEMS_INTERRUPT_UNIQUE : 
                         RTEMS_INTERRUPT_SHARED;
@@ -481,15 +438,18 @@ rtems_status_code stm32f4_gpio_remove_interrupt(
 )
 {
     stm32f4_gpio *gpio = get_gpio_from_base(base);
-    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_table[gpio->pin] = (stm32f4_interrupt){0};
+    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 sc;
+    return RTEMS_UNSATISFIED;
 }
 
 rtems_status_code stm32f4_gpio_enable_interrupt(
diff --git a/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h b/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
index 814b1b4105..2b3dd2e044 100644
--- a/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
+++ b/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
@@ -53,6 +53,173 @@ typedef struct {
     GPIO_TypeDef *port;
 } stm32f4_gpio;
 
+/**
+  * @brief Initializes clock for the GPIO port
+  *        owning this pin.
+  *
+  * @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 Does nothing.
+  *
+  * @param[in] base The pointer to the GPIO object.
+  * 
+  * @retval RTEMS_NOT_IMPLEMENTED
+  */
+extern rtems_status_code stm32f4_gpio_deinit(
+    rtems_gpio *base
+);
+
+/**
+  * @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
+);
+
 /**
   * @brief Lock configuration of a pin.
   *
-- 
2.36.1



More information about the devel mailing list