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

Duc Doan dtbpkmte at gmail.com
Sat Jun 25 11:43:53 UTC 2022


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
);

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