[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