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 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel