[PATCH] Proposal for new GPIO API and example implementation for STM32F4 BSP
Duc Doan
dtbpkmte at gmail.com
Thu Jun 23 11:36:27 UTC 2022
On Tue, 2022-06-21 at 17:23 +0200, oss at c-mauderer.de wrote:
> OK. So every BSP that want's to use that API will have a different
> rtems_gpio_config_t (or every other structure) that is defined in
> (for
> example) bsp.h? The application has to know the details of the
> current
> BSP and initialize the structure accordingly.
>
> That means that if I write an application that can run on an STM32 or
> alternatively on some RISC-V based CPU the API will be different. Not
> really portable.
>
Yes, you are right: rtems_gpio_config_t was defined by each BSP. I have
fixed by making rtems_gpio_t and rtems_gpio_config_t concrete structs
that hold common information among architectures. They also have a
pointer to a bsp-specific structure if required, like in the current
API.
/**
* @brief Structure for a GPIO object. It holds information
* like port number and pin number/pin mask.
*
*/
typedef struct {
void *port; /* Pointer to the GPIO port */
uint32_t pin_mask; /* The pin number or pin mask */
bool is_expander; /* If the GPIO is an expander, set to
true.
Else false. */
uint32_t expander_id; /* This field specifies which GPIO
expander is
in use. In case of using multiple
expanders,
this field is necessary to handle
each. */
void *bsp; /* Pointer to BSP-specific data */
} rtems_gpio_t;
/**
* @brief Structure for configuration of a GPIO object.
*/
typedef struct {
rtems_gpio_pin_mode mode; /* Pin mode */
rtems_gpio_pull pull; /* Pull resistor configuration */
void *bsp; /* Pointer to BSP-specific config */
} rtems_gpio_config_t;
Hopefully this makes the application code more portable. I have also
updated the blink code:
https://github.com/dtbpkmte/GSoC-2022-RTEMS-Sample-Apps/blob/main/RTEMS_Blink_API/src/init.c
This time, for simple tasks like basic I/O, users won't need to care
about the details of a BSP.
One thing I am not sure about is that do all architectures have ports
and pins for GPIO? I am worried that my structure is still skewed
towards STM32 because I don't have much knowledge about different types
of microcontrollers.
> If you ask me: We have SYSINIT functions for this kind of
> initializations. If something should be done at about bsp_start, the
> user can register a function at RTEMS_SYSINIT_BSP_START.
Thank you for the suggestion. This is what I have and it seems to be
working:
RTEMS_SYSINIT_ITEM(
rtems_gpio_initialize,
RTEMS_SYSINIT_BSP_START,
RTEMS_SYSINIT_ORDER_LAST
);
>
>
> I think I haven't written clearly what I meant: Let's assume a I2C
> chip
> like the TCA9537 from TI (can be any other GPIO expander from any
> other
> vendor): You connect it to a I2C bus and control 4 GPIOs with it.
> It's a
> GPIO so a good GPIO API should be able to handle it.
>
> In that case the GPIO API would do some I2C transfers under the hood
> if
> you switch or read a GPIO. So what happens if some error happens
> during
> one of these transfers. If the only error option is UNSATISFIED, the
> application can't distinguish the errors. It only knows something
> didn't
> work. It can't (for example) retry only on certain error cases like
> if
> the bus is busy.
>
> Please also note that the I2C GPIO expander is one example where a
> BSP
> would have two completely different GPIO controllers: A number of
> integrated ones and a number of I2C ones. A generic API should be
> able
> to handle that case too.
I understand what you mean now. I have added that capability to by
creating the field is_expander to select between integrated GPIO and
expander. I also have a field called expander_id to select among
multiple expanders. You can see those in the rtems_gpio_t struct above.
The API function prototypes stay the same, but the BSP now need to
implement 2 functions in private: one is the "*_default" function which
controls the built-in GPIO and the other is the "*_ex" function which
controls the expander. Here are the example read and write functions,
which are in bsps/shared/dev/gpio/gpio.c:
rtems_status_code rtems_gpio_write_pin(rtems_gpio_t *gpiox,
rtems_gpio_pin_state value) {
if (gpiox->is_expander) {
return rtems_gpio_write_pin_ex(gpiox, value);
} else {
return rtems_gpio_write_pin_default(gpiox, value);
}
}
rtems_status_code rtems_gpio_read_pin(rtems_gpio_t *gpiox,
rtems_gpio_pin_state *value) {
if (gpiox->is_expander) {
return rtems_gpio_read_pin_ex(gpiox, value);
} else {
return rtems_gpio_read_pin_default(gpiox, value);
}
}
> >
Please give me more feedback. Thank you very much.
Best,
Duc Doan
>
More information about the devel
mailing list