[PATCH] Proposal for new GPIO API and example implementation for STM32F4 BSP

oss at c-mauderer.de oss at c-mauderer.de
Sun Jun 26 07:50:07 UTC 2022


Hello Duc,

Am 25.06.22 um 13:43 schrieb Duc Doan:
> Hello Christian,
> 
> On Fri, 2022-06-24 at 17:32 +0200, oss at c-mauderer.de wrote:
>> Be careful with everything that depends on the BSP. Again: Please
>> think
>> about an i2c GPIO expander. That chip can be used on different BSPs.
>> It
>> can be even an independent driver that can be used by a user on
>> demand
>> on any BSP that supports i2c.
> 
> I ended up using a void* so that users can pass anything into it and
> the driver/BSP will cast and parse it. Is that a good solution?
> 
> Also, here is my updated API:
> 
> File: gpio2.h  /********* API header **********/
> 
> typedef struct rtems_gpio_handlers rtems_gpio_handlers_t;
> typedef struct rtems_gpio_ctrl rtems_gpio_ctrl_t;
> typedef struct rtems_gpio_config rtems_gpio_config_t;
> typedef struct rtems_gpio_interrupt_config
> rtems_gpio_interrupt_config_t;
> 
> struct rtems_gpio_handlers {
>      rtems_status_code (*initialize)(rtems_gpio_ctrl_t *);
> 
>      rtems_status_code (*deinitialize)(rtems_gpio_ctrl_t *);
> 
>      rtems_status_code (*configure)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_config_t *);
> 
>      rtems_status_code (*configure_interrupt)(rtems_gpio_ctrl_t *, void
> *, rtems_gpio_interrupt_config_t *);
> 
>      rtems_status_code (*enable_interrupt)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_interrupt_config_t *);
> 
>      rtems_status_code (*disable_interrupt)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_interrupt_config_t *);
> 
>      rtems_status_code (*set_pin_mode)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_pin_mode);
> 
>      rtems_status_code (*set_pull)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_pull);
> 
>      rtems_status_code (*read)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_pin_state *);
> 
>      rtems_status_code (*write)(rtems_gpio_ctrl_t *, void *,
> rtems_gpio_pin_state);
> 
>      rtems_status_code (*toggle)(rtems_gpio_ctrl_t *, void *);
> 
> };
> 
> struct rtems_gpio_ctrl {
>      const rtems_gpio_handlers_t *handlers;
> };
> 
> struct rtems_gpio_config {
>      rtems_gpio_pin_mode mode;   /* Pin mode */
>      rtems_gpio_pull pull;       /* Pull resistor configuration */
> };
> 
> struct rtems_gpio_interrupt_config {
>      rtems_gpio_interrupt interrupt_mode;        /* Interrupt trigger
> mode */
>      uint32_t interrupt_number;                  /* Interrupt number */
>      uint32_t priority;                          /* Interrupt priority
> */
>      void *bsp;                                  /* Pointer to BSP-
> specific config */
>      void (*handler) (void *arg);                /* Pointer to the IRQ
> handler */
>      void *arg;                                  /* Pointer to the
> arguments of IRQ handler */
> };
> 
> extern void rtems_gpio_register(
>      rtems_gpio_ctrl_t *base,
>      const rtems_gpio_handlers_t *handlers
> );
> 
> extern rtems_status_code rtems_gpio_initialize(
>      rtems_gpio_ctrl_t *base
> );
> 
> extern rtems_status_code rtems_gpio_deinitialize(
>      rtems_gpio_ctrl_t *base
> );
> 
> extern rtems_status_code rtems_gpio_configure(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_config_t *config
> );
> 
> extern rtems_status_code rtems_gpio_set_pin_mode(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_mode mode
> );
> 
> extern rtems_status_code rtems_gpio_set_pull(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pull pull
> );

Is setting the pull really independent of the mode? Most controller that 
I know have a pull-Up only on Inputs. Sometimes on an Open-Drain output. 
Sometimes in another controller (but you might ignore that option). 
Somethimes you can also set a different strength like 10k pull-up or 
100k pull-up.

Best regards

Christian

> 
> extern rtems_status_code rtems_gpio_configure_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> );
> 
> extern rtems_status_code rtems_gpio_enable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> );
> 
> extern rtems_status_code rtems_gpio_disable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> );
> 
> extern rtems_status_code rtems_gpio_write(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state value
> );
> 
> extern rtems_status_code rtems_gpio_read(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state *value
> );
> 
> extern rtems_status_code rtems_gpio_ctrl_toggle(
>      rtems_gpio_ctrl_t *base,
>      void *pin
> );
> /************************************************/
> 
> File: gpio.c (API source)
> 
> #include <bsp/gpio2.h>
> 
> void rtems_gpio_register(
>      rtems_gpio_ctrl_t *base,
>      const rtems_gpio_handlers_t *handlers
> )
> {
>      base->handlers = handlers;
> }
> 
> rtems_status_code rtems_gpio_initialize(
>      rtems_gpio_ctrl_t *base
> )
> {
>      return base->handlers->initialize(base);
> }
> 
> rtems_status_code rtems_gpio_deinitialize(
>      rtems_gpio_ctrl_t *base
> )
> {
>      return base->handlers->deinitialize(base);
> }
> 
> rtems_status_code rtems_gpio_configure(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_config_t *config
> )
> {
>      return base->handlers->configure(base, pin, config);
> }
> 
> rtems_status_code rtems_gpio_set_pin_mode(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_mode mode
> )
> {
>      return base->handlers->set_pin_mode(base, pin, mode);
> }
> 
> rtems_status_code rtems_gpio_set_pull(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pull pull
> )
> {
>      return base->handlers->set_pull(base, pin, pull);
> }
> 
> rtems_status_code rtems_gpio_configure_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      return base->handlers->configure_interrupt(base, pin, int_conf);
> }
> 
> rtems_status_code rtems_gpio_enable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      return base->handlers->enable_interrupt(base, pin, int_conf);
> }
> 
> rtems_status_code rtems_gpio_disable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      return base->handlers->disable_interrupt(base, pin, int_conf);
> }
> 
> rtems_status_code rtems_gpio_write(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state value
> )
> {
>      return base->handlers->write(base, pin, value);
> }
> 
> rtems_status_code rtems_gpio_read(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state *value
> )
> {
>      return base->handlers->read(base, pin, value);
> }
> 
> rtems_status_code rtems_gpio_ctrl_toggle(
>      rtems_gpio_ctrl_t *base,
>      void *pin
> )
> {
>      return base->handlers->toggle(base, pin);
> }
> /**************************************************/
> 
> File: stm32f4_gpio.h (Header for STM32F4 GPIO)
> 
> typedef struct {
>      rtems_gpio_ctrl_t base;
>      GPIO_TypeDef *port;
>      bool is_registered;
> } stm32f4_gpio_ctrl_t;
> 
> /**
>    * @brief STM32F4-specific interrupt configuration structure.
>    */
> typedef struct {
>      rtems_gpio_interrupt_config_t base;
>      uint32_t subpriority;  /* Subpriority level of the IRQ */
>      bool is_event_mode;     /* Set to true if using Event mode */
> } stm32f4_gpio_interrupt_config_t;
> 
> typedef struct {
>      rtems_gpio_config_t base;   /* Base GPIO config object */
> 
>      uint32_t speed;             /* Speed of the pin. Must be specified
> */
> 
>      uint32_t alternate_mode;    /* Open drain or Push-pull mode
>                                     Use if the pin is in Alternate mode
> */
>      uint32_t alternate_fn;      /* The alternate function of the pin
>                                     Use if the pin is in Alternate mode
> */
> } stm32f4_gpio_config_t;
> 
> rtems_status_code stm32f4_gpio_get_ctrl(GPIO_TypeDef *port,
> rtems_gpio_ctrl_t **out);
> 
> /************************************************/
> 
> File: bsps/arm/stm32f4/gpio/gpio.c (STM32F4 GPIO source)
> 
> #include <bsp.h>
> #include <rtems.h>
> #include <bsp/stm32f4_gpio.h>
> 
> static rtems_status_code stm32f4_gpio_initialize(
>      rtems_gpio_ctrl_t *base
> );
> 
> static rtems_status_code stm32f4_gpio_deinitialize(
>      rtems_gpio_ctrl_t *base
> );
> 
> static rtems_status_code stm32f4_gpio_configure(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_config_t *config
> );
> 
> static rtems_status_code stm32f4_gpio_configure_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> );
> 
> static rtems_status_code stm32f4_gpio_enable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> );
> 
> static rtems_status_code stm32f4_gpio_disable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> );
> 
> static rtems_status_code stm32f4_gpio_set_pin_mode(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_mode mode
> );
> 
> static rtems_status_code stm32f4_gpio_set_pull(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pull pull
> );
> 
> static rtems_status_code stm32f4_gpio_read(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state *value
> );
> static rtems_status_code stm32f4_gpio_write(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state value
> );
> 
> static rtems_status_code stm32f4_gpio_toggle(
>      rtems_gpio_ctrl_t *base,
>      void *pin
> );
> 
> static const rtems_gpio_handlers_t stm32f4_gpio_handlers = {
>      .initialize = stm32f4_gpio_initialize,
>      .deinitialize = stm32f4_gpio_deinitialize,
>      .configure = stm32f4_gpio_configure,
>      .configure_interrupt = stm32f4_gpio_configure_interrupt,
>      .enable_interrupt = stm32f4_gpio_enable_interrupt,
>      .disable_interrupt = stm32f4_gpio_disable_interrupt,
>      .set_pin_mode = stm32f4_gpio_set_pin_mode,
>      .set_pull = stm32f4_gpio_set_pull,
>      .read = stm32f4_gpio_read,
>      .write = stm32f4_gpio_write,
>      .toggle = stm32f4_gpio_toggle
> };
> 
> stm32f4_gpio_ctrl_t gpioa_ctrl = { .port = GPIOA };
> stm32f4_gpio_ctrl_t gpiob_ctrl = { .port = GPIOB };
> stm32f4_gpio_ctrl_t gpioc_ctrl = { .port = GPIOC };
> stm32f4_gpio_ctrl_t gpiod_ctrl = { .port = GPIOD };
> stm32f4_gpio_ctrl_t gpioe_ctrl = { .port = GPIOE };
> stm32f4_gpio_ctrl_t gpiof_ctrl = { .port = GPIOF };
> stm32f4_gpio_ctrl_t gpiog_ctrl = { .port = GPIOG };
> stm32f4_gpio_ctrl_t gpioh_ctrl = { .port = GPIOG };
> stm32f4_gpio_ctrl_t gpioi_ctrl = { .port = GPIOI };
> #ifdef STM32F429X
> stm32f4_gpio_ctrl_t gpioj_ctrl = { .port = GPIOJ };
> stm32f4_gpio_ctrl_t gpiok_ctrl = { .port = GPIOK };
> #endif /* STM32F429X */
> 
> rtems_status_code stm32f4_gpio_get_ctrl(GPIO_TypeDef *port,
> rtems_gpio_ctrl_t **out) {
>      switch ((uintptr_t) port) {
>          case (uintptr_t) GPIOA:
>              *out = (rtems_gpio_ctrl_t *) &gpioa_ctrl;
>              break;
>          case (uintptr_t) GPIOB:
>              *out = (rtems_gpio_ctrl_t *) &gpiob_ctrl;
>              break;
>          case (uintptr_t) GPIOC:
>              *out = (rtems_gpio_ctrl_t *) &gpioc_ctrl;
>              break;
>          case (uintptr_t) GPIOD:
>              *out = (rtems_gpio_ctrl_t *) &gpiod_ctrl;
>              break;
>          case (uintptr_t) GPIOE:
>              *out = (rtems_gpio_ctrl_t *) &gpioe_ctrl;
>              break;
>          case (uintptr_t) GPIOF:
>              *out = (rtems_gpio_ctrl_t *) &gpiof_ctrl;
>              break;
>          case (uintptr_t) GPIOG:
>              *out = (rtems_gpio_ctrl_t *) &gpiog_ctrl;
>              break;
>          case (uintptr_t) GPIOH:
>              *out = (rtems_gpio_ctrl_t *) &gpiog_ctrl;
>              break;
>          case (uintptr_t) GPIOI:
>              *out = (rtems_gpio_ctrl_t *) &gpioi_ctrl;
>              break;
> #ifdef STM32F429X
>          case (uintptr_t) GPIOJ:
>              *out = (rtems_gpio_ctrl_t *) &gpioj_ctrl;
>              break;
>          case (uintptr_t) GPIOK:
>              *out = (rtems_gpio_ctrl_t *) &gpiok_ctrl;
>              break;
> #endif /* STM32F429X */
>          default:
>              return RTEMS_UNSATISFIED;
>      }
>      if (((stm32f4_gpio_ctrl_t *) (*out))->is_registered == false) {
>          rtems_gpio_register(*out, &stm32f4_gpio_handlers);
>          ((stm32f4_gpio_ctrl_t *) (*out))->is_registered = true;
>      }
>      return RTEMS_SUCCESSFUL;
> }
> 
> static stm32f4_gpio_ctrl_t *get_ctrl_from_base(
>      rtems_gpio_ctrl_t *base
> )
> {
>      return RTEMS_CONTAINER_OF(base, stm32f4_gpio_ctrl_t, base);
> }
> 
> static stm32f4_gpio_config_t *get_config_from_base(
>      rtems_gpio_config_t *config
> )
> {
>      return RTEMS_CONTAINER_OF(config, stm32f4_gpio_config_t, base);
> }
> 
> static stm32f4_gpio_interrupt_config_t *get_interrupt_config_from_base(
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      return RTEMS_CONTAINER_OF(int_conf,
> stm32f4_gpio_interrupt_config_t, base);
> }
> 
> static rtems_status_code stm32f4_gpio_initialize(rtems_gpio_ctrl_t
> *base) {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      
>      switch ((uintptr_t) ctrl->port) {
>          case (uintptr_t) GPIOA:
>              __HAL_RCC_GPIOA_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOB:
>              __HAL_RCC_GPIOB_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOC:
>              __HAL_RCC_GPIOC_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOD:
>              __HAL_RCC_GPIOD_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOE:
>              __HAL_RCC_GPIOE_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOF:
>              __HAL_RCC_GPIOF_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOG:
>              __HAL_RCC_GPIOG_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOH:
>              __HAL_RCC_GPIOH_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOI:
>              __HAL_RCC_GPIOI_CLK_ENABLE();
>              break;
> #ifdef STM32F429X
>          case (uintptr_t) GPIOJ:
>              __HAL_RCC_GPIOJ_CLK_ENABLE();
>              break;
>          case (uintptr_t) GPIOK:
>              __HAL_RCC_GPIOK_CLK_ENABLE();
>              break;
> #endif /* STM32F429X */
>          default:
>              return RTEMS_UNSATISFIED;
>      }
>      return RTEMS_SUCCESSFUL;
> }
> 
> static rtems_status_code stm32f4_gpio_deinitialize(rtems_gpio_ctrl_t
> *base) {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      
>      switch ((uintptr_t) ctrl->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 /* STM32F429X */
>          default:
>              return RTEMS_UNSATISFIED;
>      }
>      return RTEMS_SUCCESSFUL;
> }
> 
> /**
>    * @note Warning: only one pin can be passed as argument
>    * @note If using interrupt mode, use
> rtems_gpio_configure_interrupt().
>    * @note If using alternate mode, use rtems_gpio_configure().
>    */
> rtems_status_code stm32f4_gpio_set_pin_mode(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_mode mode
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      uint32_t pin_mask = *(uint32_t *)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:
>          /* use rtems_gpio_configure() instead */
>          stm32f4_mode = LL_GPIO_MODE_ALTERNATE;
>          break;
>      default:
>          /* illegal argument */
>          return RTEMS_UNSATISFIED;
>      }
>      LL_GPIO_SetPinMode((GPIO_TypeDef *) ctrl->port, pin_mask,
> stm32f4_mode);
>      if (stm32f4_mode == LL_GPIO_MODE_OUTPUT) {
>          LL_GPIO_SetPinOutputType((GPIO_TypeDef *) ctrl->port, pin_mask,
> stm32f4_output_type);
>      }
> 
>      return RTEMS_SUCCESSFUL;
> }
> 
> /**
>    * @note Warning: only one pin can be passed as argument
>    */
> rtems_status_code stm32f4_gpio_set_pull(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pull pull
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      uint32_t pin_mask = *(uint32_t *)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_TypeDef *) ctrl->port, pin_mask,
> stm32f4_pull);
>      return RTEMS_SUCCESSFUL;
> }
> 
> rtems_status_code stm32f4_gpio_configure(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_config_t *config
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      stm32f4_gpio_config_t *stm32_conf = get_config_from_base(config);
>      uint32_t pin_mask = *(uint32_t *)pin;
>      GPIO_InitTypeDef init_struct;
> 
>      // Pin number
>      init_struct.Pin = pin_mask;
>      
>      // Pin mode
>      switch (config->mode) {
>      case RTEMS_GPIO_PINMODE_OUTPUT_PP:
>          init_struct.Mode = GPIO_MODE_OUTPUT_PP;
>          break;
>      case RTEMS_GPIO_PINMODE_OUTPUT_OD:
>          init_struct.Mode = GPIO_MODE_OUTPUT_OD;
>          break;
>      case RTEMS_GPIO_PINMODE_INPUT:
>          init_struct.Mode = GPIO_MODE_INPUT;
>          break;
>      case RTEMS_GPIO_PINMODE_ANALOG:
>          init_struct.Mode = GPIO_MODE_ANALOG;
>          break;
>      case RTEMS_GPIO_PINMODE_BSP_SPECIFIC:
>          /* Alternate mode */
>          init_struct.Mode = stm32_conf->alternate_mode;
>          break;
>      default:
>          /* illegal argument */
>          return RTEMS_UNSATISFIED;
>      }
> 
>      // Pin pull resistor
>      switch (config->pull) {
>          case RTEMS_GPIO_NOPULL:
>              init_struct.Pull = GPIO_NOPULL;
>              break;
>          case RTEMS_GPIO_PULLUP:
>              init_struct.Pull = GPIO_PULLUP;
>              break;
>          case RTEMS_GPIO_PULLDOWN:
>              init_struct.Pull = GPIO_PULLDOWN;
>              break;
>          default:
>              return RTEMS_UNSATISFIED;
>      }
>      
>      // Pin speed
>      init_struct.Speed = stm32_conf->speed;
> 
>      // Pin alternate functionality
>      if (config->mode == RTEMS_GPIO_PINMODE_BSP_SPECIFIC) {
>          init_struct.Alternate = stm32_conf->alternate_fn;
>      }
> 
>      // Call HAL to configure the GPIO pin
>      HAL_GPIO_Init(ctrl->port, &init_struct);
> 
>      return RTEMS_SUCCESSFUL;
> }
> 
> /**
>    * TODO
>    *
>    * @note This function defaults to not using pull resistor.
>    *       Use rtems_gpio_set_pull() afterwards to change.
>    */
> rtems_status_code stm32f4_gpio_configure_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      stm32f4_gpio_interrupt_config_t *stm32_int_conf =
> get_interrupt_config_from_base(int_conf);
>      uint32_t pin_mask = *(uint32_t *)pin;
>      GPIO_InitTypeDef hal_conf;
> 
>      switch (int_conf->interrupt_mode) {
>      case RTEMS_GPIO_INT_MODE_NONE:
>          return RTEMS_SUCCESSFUL;
>      case RTEMS_GPIO_INT_MODE_FALLING:
>          if (stm32_int_conf->is_event_mode) {
>              hal_conf.Mode = GPIO_MODE_EVT_FALLING;
>          } else {
>              hal_conf.Mode = GPIO_MODE_IT_FALLING;
>          }
>          break;
>      case RTEMS_GPIO_INT_MODE_RISING:
>          if (stm32_int_conf->is_event_mode) {
>              hal_conf.Mode = GPIO_MODE_EVT_RISING;
>          } else {
>              hal_conf.Mode = GPIO_MODE_IT_RISING;
>          }
>          break;
>      case RTEMS_GPIO_INT_MODE_BOTH_EDGES:
>          if (stm32_int_conf->is_event_mode) {
>              hal_conf.Mode = GPIO_MODE_EVT_RISING_FALLING;
>          } else {
>              hal_conf.Mode = GPIO_MODE_IT_RISING_FALLING;
>          }
>          break;
>      default:
>          /* Invalid argument */
>          return RTEMS_UNSATISFIED;
>      }
>      hal_conf.Pull = GPIO_NOPULL;
>      hal_conf.Pin = pin_mask;
>      HAL_GPIO_Init(ctrl->port, &hal_conf);
> 
>      HAL_NVIC_SetPriority((IRQn_Type) int_conf->interrupt_number,
> int_conf->priority, stm32_int_conf->subpriority);
> 
>      return RTEMS_SUCCESSFUL;
> }
> 
> static rtems_status_code stm32f4_gpio_enable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      HAL_NVIC_EnableIRQ((IRQn_Type) int_conf->interrupt_number);
>      return RTEMS_SUCCESSFUL;
> }
> 
> static rtems_status_code stm32f4_gpio_disable_interrupt(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_interrupt_config_t *int_conf
> )
> {
>      HAL_NVIC_DisableIRQ((IRQn_Type) int_conf->interrupt_number);
>      return RTEMS_SUCCESSFUL;
> }
> 
> rtems_status_code stm32f4_gpio_write(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state value
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      uint32_t pin_mask = *(uint32_t *)pin;
> 
>      HAL_GPIO_WritePin(ctrl->port, pin_mask, value);
>      return RTEMS_SUCCESSFUL;
> }
> 
> rtems_status_code stm32f4_gpio_read(
>      rtems_gpio_ctrl_t *base,
>      void *pin,
>      rtems_gpio_pin_state *value
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      uint32_t pin_mask = *(uint32_t *)pin;
> 
>      *value = HAL_GPIO_ReadPin(ctrl->port, pin_mask);
>      return RTEMS_SUCCESSFUL;
> }
> 
> rtems_status_code stm32f4_gpio_toggle(
>      rtems_gpio_ctrl_t *base,
>      void *pin
> )
> {
>      stm32f4_gpio_ctrl_t *ctrl = get_ctrl_from_base(base);
>      uint32_t pin_mask = *(uint32_t *)pin;
> 
>      HAL_GPIO_TogglePin(ctrl->port, pin_mask);
>      return RTEMS_SUCCESSFUL;
> }
> /**********************************************************/
> 
> I am still testing and modifying the external interrupt part.
> 
> Please let me know what you think the code. Thank you.
> 
> Best,
> 
> Duc Doan
> 


More information about the devel mailing list