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

2022-06-29 Thread oss

Hello Duc,

Am 29.06.22 um 13:46 schrieb Duc Doan:

Hello Christian,

I have been writing the complete API and also implementation for
STM32F4. A patch is coming soon.

On Mon, 2022-06-27 at 13:33 +0200, Christian MAUDERER wrote:

Regarding pin groups: I think it's worth to think a bit about how the
structure could be extended. You don't have to implement it right now
but you should have a plan what could be possible.

  From my point of view, there are two directions how that could be
implemented: Masks or lists.

If you have a mask (like 0x00108 for pin 3 and pin 8) it has the
advantage that it works fast for most controllers. Difficult is that
it
adds a limit to the maximum pin number depending on the size of the
mask. With that it works only for a few hardware models.

The other option is to add a list of pins instead of a mask. That
makes
it inefficient because most controllers will have to collect pins
into
masks and work with that.

Hm. Difficult. Maybe someone else has a good idea for that in the
next
few days.


I am thinking of later adding separate functions that handle pin
groups. I think it's quite hard to integrate into current functions
because of using virtual pin.

I have an assumption that needs confirmation: all microcontrollers (or
most of them) have register size equal to word size, and pin masks
should be at word size. Is that assumption correct? If so, maybe we can
just use unsigned int (or uintptr_t) for pin masks?


Not sure whether some 64bit controllers don't use 32bit registers. So 
it's not generally true that registers have the word size. It should 
work for most controllers (at least the ones I worked with) but I 
wouldn't guarantee it.


Beneath that: You most likely know my argument already: What about I2C 
or SPI chips. They can use register sizes that are not the same as the 
controllers register size (even if they are most likely only 8 bit most 
of the time at least for I2C).


Best regards

Christian



Best,

Duc Doan



___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-29 Thread Duc Doan
Hello Christian,

I have been writing the complete API and also implementation for
STM32F4. A patch is coming soon.

On Mon, 2022-06-27 at 13:33 +0200, Christian MAUDERER wrote:
> Regarding pin groups: I think it's worth to think a bit about how the
> structure could be extended. You don't have to implement it right now
> but you should have a plan what could be possible.
> 
>  From my point of view, there are two directions how that could be 
> implemented: Masks or lists.
> 
> If you have a mask (like 0x00108 for pin 3 and pin 8) it has the 
> advantage that it works fast for most controllers. Difficult is that
> it 
> adds a limit to the maximum pin number depending on the size of the 
> mask. With that it works only for a few hardware models.
> 
> The other option is to add a list of pins instead of a mask. That
> makes 
> it inefficient because most controllers will have to collect pins
> into 
> masks and work with that.
> 
> Hm. Difficult. Maybe someone else has a good idea for that in the
> next 
> few days.

I am thinking of later adding separate functions that handle pin
groups. I think it's quite hard to integrate into current functions
because of using virtual pin.

I have an assumption that needs confirmation: all microcontrollers (or
most of them) have register size equal to word size, and pin masks
should be at word size. Is that assumption correct? If so, maybe we can
just use unsigned int (or uintptr_t) for pin masks?

Best,

Duc Doan


___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-27 Thread Christian MAUDERER

Hello Duc,

Am 27.06.22 um 12:39 schrieb Duc Doan:

Hello Christian and Karel,

On Mon, 2022-06-27 at 08:29 +0200, Christian MAUDERER wrote:

Please think about whether you want to start at 0 or at 1!



I want it to start at 0.



Be really careful with that syntax. If you use increasing numbers
like
you suggested, every controller would have to know it's own offest.
On
the other hand, if there is a unique number to each pin, you don't
necessarily need the "ctrl" pointer at all. You can just use
something like

     rtems_gpio_write(60, RTEMS_GPIO_PIN_SET);

That's an advantage from the usage perspective because you don't have
to
fetch the GPIO controller and can work with a single pin number.

Disadvantage is a overhead in the API: You have to create some global
table with GPIO controllers and their first and last pins. That table
has to be searched for every operation. In the worst case it adds a
loop
over the table with one comparison for each entry. Most systems
should
only have a hand full of GPIO controller so it's not too much but
it's a
lot more than just one pointer de-referencing. There could be methods
to
optimize the search so the loop might isn't the best solution. But
every
search is slower than if you already have the pointer.

It's more or less a trade-off. There are good arguments for both
directions. I think I have seen both directions implemented in
different
situations.



You are right; having both ctrl and virtual pin number is abundant.
Karel's email gave me some inspiration to (hopefully) improve this:

On Mon, 2022-06-27 at 10:25 +0200, Karel Gardas wrote:

In fact I guess ctrl structure would contain some BSP specific data
and
since bsp_gpio_get_ctrl is BSP specific function for f4 that means in
ctrl you will save your GPIOx and pin number -- e.g. hardware
specific
pin representation.

This means on write/read you do not need to map virtual pin ->
physical
pin again, but in fact use physical pin from ctrl and be as fast as
possible.



Actually as of now, my ctrl structure only has pointers to handlers and
GPIOx (F4 only). Pin number was not in there, but I am thinking
including pin number inside that structure might work. The changes I
want to make would be:

- ctrl structure will now include both pointers to handlers and BSP-
specific physical port/pin

struct rtems_gpio_ctrl {
 rtems_gpio_handlers_t *handlers;
}

struct stm32f4_gpio_ctrl {
 rtems_gpio_ctrl base;
 GPIO_TypeDef *GPIOx;
 uint32_t pin; //physical
}

- I will create 2 internal tables (based on Christian's suggestion) to
store the last pins of each controller and pointers to the get_ctrl()
functions. For example, if STM32 has 16 pins per port and 4 ports in
total, my table would be:

uint32_t table[MAX_CONTROLLERS] = {16, 32, 48, 64};

These numbers and the controller pointers are added to the tables by
calling a register() function for each controller. BSPs need to
implement an initialize() function. The prototype of initialize() is
provided by the GPIO API. initialize() needs to be called before any
GPIO operation in the application.

If GPIO expanders exist, their drivers need to have similar initialize
functions that call the register().

Currently I can only think of binary search as a faster method than a
for loop. rtems_gpio_get_ctrl(virtual_pin) will search for the correct
controller, call the BSP/driver-specific get_ctrl(), and return the
result.

- Because pin number is now in ctrl, functions only need to provide
pointer to ctrl object.

Below is an example program with a fake STM32 with 4 GPIOs/16 pins
each. Two GPIO expanders (exA, exB) are used.

/** API header ***/
void register(void (*get_ctrl) (uint32_t pin), uint32_t num_pins); //
shared, already implemented
void initialize(void); // to be implemented by BSP

/** stm32f4 gpio.c **/
void rtems_gpio_initialize(void) {
 register(stm32f4_get_ctrl, 16); // port A
 register(stm32f4_get_ctrl, 16); // port B
 register(stm32f4_get_ctrl, 16); // port C
 register(stm32f4_get_ctrl, 16); // port D
}

/* application blink.c ***/

// initialization
rtems_gpio_initialize();
exA_initialize(); // registers pins to the table
exB_initialize(); // registers pins to the table

uint32_t led_pin = 60; // just a random number
rtems_gpio_ctrl_t *led_ctrl = rtems_gpio_get_ctrl(60);

rtems_gpio_write(led_ctrl, RTEMS_GPIO_PIN_SET);


I think I misinterpreted the rtems_gpio_ctrl_t in my earlier mail. With 
this example it's now much clearer that the rtems_gpio_ctrl_t now 
represents a pin (or maybe a pin group) and not a controller any more. I 
would suggest to rename it to rtems_gpio_t or rtems_gpio_pin_t to make 
that more clear. Otherwise: OK for me.




/* END OF EXAMPLE **/

The only place where the search must be done is now in get_ctrl(), so
read/write operations are still fast. One drawback of this approach
might be the support for pin groups, but currently I have quite little

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

2022-06-27 Thread Duc Doan
Hello Christian and Karel,

On Mon, 2022-06-27 at 08:29 +0200, Christian MAUDERER wrote:
> Please think about whether you want to start at 0 or at 1!
> 

I want it to start at 0.

> 
> Be really careful with that syntax. If you use increasing numbers
> like 
> you suggested, every controller would have to know it's own offest.
> On 
> the other hand, if there is a unique number to each pin, you don't 
> necessarily need the "ctrl" pointer at all. You can just use
> something like
> 
>     rtems_gpio_write(60, RTEMS_GPIO_PIN_SET);
> 
> That's an advantage from the usage perspective because you don't have
> to 
> fetch the GPIO controller and can work with a single pin number.
> 
> Disadvantage is a overhead in the API: You have to create some global
> table with GPIO controllers and their first and last pins. That table
> has to be searched for every operation. In the worst case it adds a
> loop 
> over the table with one comparison for each entry. Most systems
> should 
> only have a hand full of GPIO controller so it's not too much but
> it's a 
> lot more than just one pointer de-referencing. There could be methods
> to 
> optimize the search so the loop might isn't the best solution. But
> every 
> search is slower than if you already have the pointer.
> 
> It's more or less a trade-off. There are good arguments for both 
> directions. I think I have seen both directions implemented in
> different 
> situations.
> 

You are right; having both ctrl and virtual pin number is abundant.
Karel's email gave me some inspiration to (hopefully) improve this:

On Mon, 2022-06-27 at 10:25 +0200, Karel Gardas wrote:
> In fact I guess ctrl structure would contain some BSP specific data
> and 
> since bsp_gpio_get_ctrl is BSP specific function for f4 that means in
> ctrl you will save your GPIOx and pin number -- e.g. hardware
> specific 
> pin representation.
> 
> This means on write/read you do not need to map virtual pin ->
> physical 
> pin again, but in fact use physical pin from ctrl and be as fast as 
> possible.
> 

Actually as of now, my ctrl structure only has pointers to handlers and
GPIOx (F4 only). Pin number was not in there, but I am thinking
including pin number inside that structure might work. The changes I
want to make would be:

- ctrl structure will now include both pointers to handlers and BSP-
specific physical port/pin

struct rtems_gpio_ctrl {
rtems_gpio_handlers_t *handlers;
}

struct stm32f4_gpio_ctrl {
rtems_gpio_ctrl base;
GPIO_TypeDef *GPIOx;
uint32_t pin; //physical
}

- I will create 2 internal tables (based on Christian's suggestion) to
store the last pins of each controller and pointers to the get_ctrl()
functions. For example, if STM32 has 16 pins per port and 4 ports in
total, my table would be:

uint32_t table[MAX_CONTROLLERS] = {16, 32, 48, 64};

These numbers and the controller pointers are added to the tables by
calling a register() function for each controller. BSPs need to
implement an initialize() function. The prototype of initialize() is
provided by the GPIO API. initialize() needs to be called before any
GPIO operation in the application.

If GPIO expanders exist, their drivers need to have similar initialize
functions that call the register().

Currently I can only think of binary search as a faster method than a
for loop. rtems_gpio_get_ctrl(virtual_pin) will search for the correct
controller, call the BSP/driver-specific get_ctrl(), and return the
result.

- Because pin number is now in ctrl, functions only need to provide
pointer to ctrl object. 

Below is an example program with a fake STM32 with 4 GPIOs/16 pins
each. Two GPIO expanders (exA, exB) are used.

/** API header ***/
void register(void (*get_ctrl) (uint32_t pin), uint32_t num_pins); //
shared, already implemented
void initialize(void); // to be implemented by BSP

/** stm32f4 gpio.c **/
void rtems_gpio_initialize(void) {
register(stm32f4_get_ctrl, 16); // port A
register(stm32f4_get_ctrl, 16); // port B
register(stm32f4_get_ctrl, 16); // port C
register(stm32f4_get_ctrl, 16); // port D 
}

/* application blink.c ***/

// initialization
rtems_gpio_initialize();
exA_initialize(); // registers pins to the table
exB_initialize(); // registers pins to the table

uint32_t led_pin = 60; // just a random number
rtems_gpio_ctrl_t *led_ctrl = rtems_gpio_get_ctrl(60);

rtems_gpio_write(led_ctrl, RTEMS_GPIO_PIN_SET);

/* END OF EXAMPLE **/

The only place where the search must be done is now in get_ctrl(), so
read/write operations are still fast. One drawback of this approach
might be the support for pin groups, but currently I have quite little
clue about that.

What do you think about these changes?

Thank you,

Duc Doan

> > 
> > This, however, only returns integrated GPIO from a BSP. In order to
> > use
> > a GPIO expansion, a separate function must be used. Each GPIO
> > expander
> > driver will have its own get_ctrl 

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

2022-06-27 Thread Karel Gardas



Hello Duc,

just one remark.

On 6/27/22 05:34, Duc Doan wrote:


rtems_gpio_ctrl_t *ctrl0 = bsp_gpio_get_ctrl(60); //corresponds to
GPIOD pin 12 on F4


^ if your ctrl structure knows you are working with pin 60


rtems_gpio_write(ctrl, 60, RTEMS_GPIO_PIN_SET);


then you do not need to use it for write.

In fact I guess ctrl structure would contain some BSP specific data and 
since bsp_gpio_get_ctrl is BSP specific function for f4 that means in 
ctrl you will save your GPIOx and pin number -- e.g. hardware specific 
pin representation.


This means on write/read you do not need to map virtual pin -> physical 
pin again, but in fact use physical pin from ctrl and be as fast as 
possible.


Christian described everything else already so no need to add anything here.

I'm glad you are making this steady progress on this project.

Thanks,
Karel
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


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

2022-06-27 Thread Christian MAUDERER

Hello Duc,

Am 27.06.22 um 05:34 schrieb Duc Doan:

Hello Karel and Christian,

I am thinking of this way: referring to a pin using a number. Each BSP
will map that pin number to its specific port and pin. For example, for
STM32F4 which has 16 pins per GPIO port, pin 6 will correspond to GPIOA
pin 6, and pin 20 will correspond to GPIOB pin 4. The get controller
function will be as follow:


That numbering scheme is used by for example Linux. Seems to work for 
them as an universal one so I don't think that we should get problems.


Please think about whether you want to start at 0 or at 1!



rtems_gpio_ctrl_t *bsp_gpio_get_ctrl(uint32_t pin);

This function must be implemented by each BSP. This will take the pin
number and return the corresponding controller object. The example
application could be as follow:

rtems_gpio_ctrl_t *ctrl0 = bsp_gpio_get_ctrl(60); //corresponds to
GPIOD pin 12 on F4

rtems_gpio_write(ctrl, 60, RTEMS_GPIO_PIN_SET);


Be really careful with that syntax. If you use increasing numbers like 
you suggested, every controller would have to know it's own offest. On 
the other hand, if there is a unique number to each pin, you don't 
necessarily need the "ctrl" pointer at all. You can just use something like


   rtems_gpio_write(60, RTEMS_GPIO_PIN_SET);

That's an advantage from the usage perspective because you don't have to 
fetch the GPIO controller and can work with a single pin number.


Disadvantage is a overhead in the API: You have to create some global 
table with GPIO controllers and their first and last pins. That table 
has to be searched for every operation. In the worst case it adds a loop 
over the table with one comparison for each entry. Most systems should 
only have a hand full of GPIO controller so it's not too much but it's a 
lot more than just one pointer de-referencing. There could be methods to 
optimize the search so the loop might isn't the best solution. But every 
search is slower than if you already have the pointer.


It's more or less a trade-off. There are good arguments for both 
directions. I think I have seen both directions implemented in different 
situations.




This, however, only returns integrated GPIO from a BSP. In order to use
a GPIO expansion, a separate function must be used. Each GPIO expander
driver will have its own get_ctrl function. For example, when using 2
different expanders exA and exB:

rtems_gpio_ctrl_t *exA_ctrl = exA_get_ctrl(pin);
rtems_gpio_ctrl_t *exB_ctrl = exB_get_ctrl(pin);


What would be the pin numbers in that case? You mentioned that the 
STM32F4 has 16 pins per GPIO. Let's assume it's 4 GPIOs so the last 
internal GPIO would be 16*4-1=63. Would the first registered expander 
have pin numbers starting at 64 or again at 0?


I would strongly suggest to use the same method for internal and 
external GPIOs. If you start with 0 for an expander, start with 0 for 
each internal GPIO controller too (in the STM example: You should have 4 
internal pins with the number 0). If you plan to have an increasing 
number, use that for the external GPIO controllers too.


Best regards

Christian



I think this method will assure that it compiles and works on all BSPs
but needs an additional function to get the controller of an expander.
A drawback might be added computation because of translating abstract
pin number to physical pin/port.

What do you think about this?

Best,

Duc Doan

On Sun, 2022-06-26 at 20:48 +0200, Karel Gardas wrote:

On 6/26/22 10:49, Duc Doan wrote:

#define rtems_gpio_get_ctrl(_driver, _arg, _out) \
   _driver##_gpio_get_ctrl( _arg , _out )

In the application code:

rtems_gpio_get_ctrl(stm32f4, GPIOD, _ctrl);
rtems_gpio_get_ctrl(stm32f4, GPIOA, _ctrl);


It's only a different method of writing the same. It won't solve
Karels
problem because it still wouldn't compile on another BSP.



Do you mean this application code should compile on other BSPs
without
changing the source?


Yes, that's exactly what portability means and that's exactly what is
desired outcome of the API here -- if I'm not mistaken in your
project
outcome specification. :-)

I'm not expert here, so please bear with me, but as I see it, you
will
need to come with some abstraction for groups and pins and write API
around it. Then in BSP you will perform/provide a mapping between
your
abstracted group/pins construct and between actual hardware. This
way,
if I take example from stm32f4 and try to compile on rpi4, it will
compile well -- but it will not run well (probably!) of course. But
API
wise, it will compile. Now, to make it run, I'll need to connect LED
example following BSP specific mapping and for that I need to consult
BSP docs.


I am a bit confused about that because I thought
at least we still need to specify the pin/port. And if we have
multiple
GPIO controllers, we still need to select one right?


Yes, and this needs to be done in abstract manner mapped down into
actual BSP implementation code. Abstract mapping here 

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

2022-06-26 Thread Duc Doan
Hello Karel and Christian,

I am thinking of this way: referring to a pin using a number. Each BSP
will map that pin number to its specific port and pin. For example, for
STM32F4 which has 16 pins per GPIO port, pin 6 will correspond to GPIOA
pin 6, and pin 20 will correspond to GPIOB pin 4. The get controller
function will be as follow:

rtems_gpio_ctrl_t *bsp_gpio_get_ctrl(uint32_t pin);

This function must be implemented by each BSP. This will take the pin
number and return the corresponding controller object. The example
application could be as follow:

rtems_gpio_ctrl_t *ctrl0 = bsp_gpio_get_ctrl(60); //corresponds to
GPIOD pin 12 on F4

rtems_gpio_write(ctrl, 60, RTEMS_GPIO_PIN_SET);

This, however, only returns integrated GPIO from a BSP. In order to use
a GPIO expansion, a separate function must be used. Each GPIO expander
driver will have its own get_ctrl function. For example, when using 2
different expanders exA and exB:

rtems_gpio_ctrl_t *exA_ctrl = exA_get_ctrl(pin);
rtems_gpio_ctrl_t *exB_ctrl = exB_get_ctrl(pin);

I think this method will assure that it compiles and works on all BSPs
but needs an additional function to get the controller of an expander.
A drawback might be added computation because of translating abstract
pin number to physical pin/port.

What do you think about this?

Best,

Duc Doan

On Sun, 2022-06-26 at 20:48 +0200, Karel Gardas wrote:
> On 6/26/22 10:49, Duc Doan wrote:
> > > > #define rtems_gpio_get_ctrl(_driver, _arg, _out) \
> > > >   _driver##_gpio_get_ctrl( _arg , _out )
> > > > 
> > > > In the application code:
> > > > 
> > > > rtems_gpio_get_ctrl(stm32f4, GPIOD, _ctrl);
> > > > rtems_gpio_get_ctrl(stm32f4, GPIOA, _ctrl);
> > > 
> > > It's only a different method of writing the same. It won't solve
> > > Karels
> > > problem because it still wouldn't compile on another BSP.
> > > 
> > 
> > Do you mean this application code should compile on other BSPs
> > without
> > changing the source?
> 
> Yes, that's exactly what portability means and that's exactly what is
> desired outcome of the API here -- if I'm not mistaken in your
> project 
> outcome specification. :-)
> 
> I'm not expert here, so please bear with me, but as I see it, you
> will 
> need to come with some abstraction for groups and pins and write API 
> around it. Then in BSP you will perform/provide a mapping between
> your 
> abstracted group/pins construct and between actual hardware. This
> way, 
> if I take example from stm32f4 and try to compile on rpi4, it will 
> compile well -- but it will not run well (probably!) of course. But
> API 
> wise, it will compile. Now, to make it run, I'll need to connect LED 
> example following BSP specific mapping and for that I need to consult
> BSP docs.
> 
> > I am a bit confused about that because I thought
> > at least we still need to specify the pin/port. And if we have
> > multiple
> > GPIO controllers, we still need to select one right?
> 
> Yes, and this needs to be done in abstract manner mapped down into 
> actual BSP implementation code. Abstract mapping here ensure
> portability 
> between BSPs/boards.
> 
> E.g. for stm32f4 you do not select GPIOA group and pin1, but you
> select 
> group 0 and pin 1 and in f4 BSP this group 0 is mapped to GPIOA and
> pin 
> 1 is mapped to its pin 1. -- something like that.
> 
> Karel

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-26 Thread Karel Gardas

On 6/26/22 10:49, Duc Doan wrote:

#define rtems_gpio_get_ctrl(_driver, _arg, _out) \
  _driver##_gpio_get_ctrl( _arg , _out )

In the application code:

rtems_gpio_get_ctrl(stm32f4, GPIOD, _ctrl);
rtems_gpio_get_ctrl(stm32f4, GPIOA, _ctrl);


It's only a different method of writing the same. It won't solve
Karels
problem because it still wouldn't compile on another BSP.



Do you mean this application code should compile on other BSPs without
changing the source?


Yes, that's exactly what portability means and that's exactly what is 
desired outcome of the API here -- if I'm not mistaken in your project 
outcome specification. :-)


I'm not expert here, so please bear with me, but as I see it, you will 
need to come with some abstraction for groups and pins and write API 
around it. Then in BSP you will perform/provide a mapping between your 
abstracted group/pins construct and between actual hardware. This way, 
if I take example from stm32f4 and try to compile on rpi4, it will 
compile well -- but it will not run well (probably!) of course. But API 
wise, it will compile. Now, to make it run, I'll need to connect LED 
example following BSP specific mapping and for that I need to consult 
BSP docs.



I am a bit confused about that because I thought
at least we still need to specify the pin/port. And if we have multiple
GPIO controllers, we still need to select one right?


Yes, and this needs to be done in abstract manner mapped down into 
actual BSP implementation code. Abstract mapping here ensure portability 
between BSPs/boards.


E.g. for stm32f4 you do not select GPIOA group and pin1, but you select 
group 0 and pin 1 and in f4 BSP this group 0 is mapped to GPIOA and pin 
1 is mapped to its pin 1. -- something like that.


Karel
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-26 Thread Duc Doan
Hello Christian and Karel,

On Sun, 2022-06-26 at 10:02 +0200, o...@c-mauderer.de wrote:
> Hello Karel and Duc,
> 
> Am 26.06.22 um 09:24 schrieb Duc Doan:
> > Hello Karel,
> > 
> > I came up with this solution: making a macro that returns a
> > function
> > depending on driver/BSP name.
> > 
> > /**
> >    * @brief Get an GPIO control object.
> >    *
> >    * This macro requires BSPs/drivers to correctly implement
> >    * function _gpio_get_ctrl(void *arg,
> >    * rtems_gpio_ctrl_t **out).
> >    *
> >    * @param _driver is the name of the BSP/GPIO driver
> >    * @param[in] _arg is the void pointer to an argument type
> >    *    defined by BSP/driver
> >    * @param[out] _out is the pointer to the pointer to where
> >    * the output object will be stored
> >    */
> > #define rtems_gpio_get_ctrl(_driver, _arg, _out) \
> >  _driver##_gpio_get_ctrl( _arg , _out )
> > 
> > In the application code:
> > 
> > rtems_gpio_get_ctrl(stm32f4, GPIOD, _ctrl);
> > rtems_gpio_get_ctrl(stm32f4, GPIOA, _ctrl);
> 
> It's only a different method of writing the same. It won't solve
> Karels 
> problem because it still wouldn't compile on another BSP.
> 

Do you mean this application code should compile on other BSPs without
changing the source? I am a bit confused about that because I thought
at least we still need to specify the pin/port. And if we have multiple
GPIO controllers, we still need to select one right? 

Best,

Duc Doan

> > 
> > What do you think about this?
> > 
> > Best,
> > 
> > Duc Doan
> > 
> > On Sat, 2022-06-25 at 21:46 +0200, Karel Gardas wrote:
> > > 
> > > Hello Duc,
> > > 
> > > one reminder, your API should be more or less portable. That
> > > means
> > > the
> > > example which you produce as a testing example should be API-wise
> > > portable between various BSPs. Is that clear?
> > > 
> > > I know, I know, sometimes user led 1 on F4 is on different
> > > port/pin
> > > on
> > > F7 and then on H7 you get it on even different port/pin, but!
> > > 
> > >   > stm32f4_gpio_get_ctrl(GPIOD, );
> > > 
> > > do you expect this to be called from app running on RPi4 for
> > > example?
> > > Or
> > > on beagle bone white? Or on stm32h757i-eval board?
> > > 
> > > Please generalize and make that bit portable too.
> 
> I think that approach is due to my suggestion to have a low overhead
> and 
> use the pointers more or less directly. A really portable method
> would 
> be to use for example device files. But for GPIO that would add a lot
> of 
> overhead which isn't good for a fast interface like that.
> 
> Another problem that I added for Duc is that I told that I might want
> to 
> register I2C GPIO expanders during the application startup.
> 
> A possibility could be to have some general bsp_gpio_get_ctrl(...) 
> function that returns the controllers for the integrated GPIOs of a
> chip 
> regardless of the chip. If you have an extra I2C expander, that will
> be 
> a separate function.
> 
> Best regards
> 
> Christian


> > 
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-26 Thread Duc Doan
Hello Christian,

On Sun, 2022-06-26 at 09:50 +0200, o...@c-mauderer.de wrote:
> 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

On STM32 I saw that there is open drain output, so pull resister could
be necessary. I think separating the pull from the mode makes it more
flexible without complicating the configuration too much. About the
strength, I think it should be in the BSP/driver-specific configuration
structure because not every controller has it.

Best,

Duc Doan
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


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

2022-06-26 Thread oss

Hello Karel and Duc,

Am 26.06.22 um 09:24 schrieb Duc Doan:

Hello Karel,

I came up with this solution: making a macro that returns a function
depending on driver/BSP name.

/**
   * @brief Get an GPIO control object.
   *
   * This macro requires BSPs/drivers to correctly implement
   * function _gpio_get_ctrl(void *arg,
   * rtems_gpio_ctrl_t **out).
   *
   * @param _driver is the name of the BSP/GPIO driver
   * @param[in] _arg is the void pointer to an argument type
   *defined by BSP/driver
   * @param[out] _out is the pointer to the pointer to where
   * the output object will be stored
   */
#define rtems_gpio_get_ctrl(_driver, _arg, _out) \
 _driver##_gpio_get_ctrl( _arg , _out )

In the application code:

rtems_gpio_get_ctrl(stm32f4, GPIOD, _ctrl);
rtems_gpio_get_ctrl(stm32f4, GPIOA, _ctrl);


It's only a different method of writing the same. It won't solve Karels 
problem because it still wouldn't compile on another BSP.




What do you think about this?

Best,

Duc Doan

On Sat, 2022-06-25 at 21:46 +0200, Karel Gardas wrote:


Hello Duc,

one reminder, your API should be more or less portable. That means
the
example which you produce as a testing example should be API-wise
portable between various BSPs. Is that clear?

I know, I know, sometimes user led 1 on F4 is on different port/pin
on
F7 and then on H7 you get it on even different port/pin, but!

  > stm32f4_gpio_get_ctrl(GPIOD, );

do you expect this to be called from app running on RPi4 for example?
Or
on beagle bone white? Or on stm32h757i-eval board?

Please generalize and make that bit portable too.


I think that approach is due to my suggestion to have a low overhead and 
use the pointers more or less directly. A really portable method would 
be to use for example device files. But for GPIO that would add a lot of 
overhead which isn't good for a fast interface like that.


Another problem that I added for Duc is that I told that I might want to 
register I2C GPIO expanders during the application startup.


A possibility could be to have some general bsp_gpio_get_ctrl(...) 
function that returns the controllers for the integrated GPIOs of a chip 
regardless of the chip. If you have an extra I2C expander, that will be 
a separate function.


Best regards

Christian



Thanks,
Karel

On 6/25/22 15:00, Duc Doan wrote:

Hello Christian,

I forgot to send the sample code. Here it a code to turn on an LED:

/*/

// Obtain the pointer to the instance (port D)
rtems_gpio_ctrl_t *ctrl;
stm32f4_gpio_get_ctrl(GPIOD, );

// enable clocks for port D
rtems_gpio_initialize(ctrl);

// configure the pin
rtems_gpio_set_pin_mode(ctrl, _PIN,
RTEMS_GPIO_PINMODE_OUTPUT_PP);
rtems_gpio_set_pull(ctrl, _PIN, RTEMS_GPIO_PULLUP);

// output to LED
rtems_gpio_write(ctrl, _PIN, RTEMS_GPIO_PIN_SET);

/*/

Best,

Duc Doan
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel




___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-26 Thread oss

Hello Duc,

Am 25.06.22 um 13:43 schrieb Duc Doan:

Hello Christian,

On Fri, 2022-06-24 at 17:32 +0200, o...@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 

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, 

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

2022-06-26 Thread Duc Doan
Hello Karel,

I came up with this solution: making a macro that returns a function
depending on driver/BSP name.

/**
  * @brief Get an GPIO control object.
  *
  * This macro requires BSPs/drivers to correctly implement
  * function _gpio_get_ctrl(void *arg, 
  * rtems_gpio_ctrl_t **out). 
  *
  * @param _driver is the name of the BSP/GPIO driver
  * @param[in] _arg is the void pointer to an argument type
  *defined by BSP/driver
  * @param[out] _out is the pointer to the pointer to where
  * the output object will be stored
  */
#define rtems_gpio_get_ctrl(_driver, _arg, _out) \
_driver##_gpio_get_ctrl( _arg , _out )

In the application code:

rtems_gpio_get_ctrl(stm32f4, GPIOD, _ctrl);
rtems_gpio_get_ctrl(stm32f4, GPIOA, _ctrl);

What do you think about this?

Best,

Duc Doan

On Sat, 2022-06-25 at 21:46 +0200, Karel Gardas wrote:
> 
> Hello Duc,
> 
> one reminder, your API should be more or less portable. That means
> the 
> example which you produce as a testing example should be API-wise 
> portable between various BSPs. Is that clear?
> 
> I know, I know, sometimes user led 1 on F4 is on different port/pin
> on 
> F7 and then on H7 you get it on even different port/pin, but!
> 
>  > stm32f4_gpio_get_ctrl(GPIOD, );
> 
> do you expect this to be called from app running on RPi4 for example?
> Or 
> on beagle bone white? Or on stm32h757i-eval board?
> 
> Please generalize and make that bit portable too.
> 
> Thanks,
> Karel
> 
> On 6/25/22 15:00, Duc Doan wrote:
> > Hello Christian,
> > 
> > I forgot to send the sample code. Here it a code to turn on an LED:
> > 
> > /*/
> > 
> > // Obtain the pointer to the instance (port D)
> > rtems_gpio_ctrl_t *ctrl;
> > stm32f4_gpio_get_ctrl(GPIOD, );
> > 
> > // enable clocks for port D
> > rtems_gpio_initialize(ctrl);
> > 
> > // configure the pin
> > rtems_gpio_set_pin_mode(ctrl, _PIN,
> > RTEMS_GPIO_PINMODE_OUTPUT_PP);
> > rtems_gpio_set_pull(ctrl, _PIN, RTEMS_GPIO_PULLUP);
> > 
> > // output to LED
> > rtems_gpio_write(ctrl, _PIN, RTEMS_GPIO_PIN_SET);
> > 
> > /*/
> > 
> > Best,
> > 
> > Duc Doan
> > ___
> > devel mailing list
> > devel@rtems.org
> > http://lists.rtems.org/mailman/listinfo/devel
> 

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-25 Thread Karel Gardas



Hello Duc,

one reminder, your API should be more or less portable. That means the 
example which you produce as a testing example should be API-wise 
portable between various BSPs. Is that clear?


I know, I know, sometimes user led 1 on F4 is on different port/pin on 
F7 and then on H7 you get it on even different port/pin, but!


> stm32f4_gpio_get_ctrl(GPIOD, );

do you expect this to be called from app running on RPi4 for example? Or 
on beagle bone white? Or on stm32h757i-eval board?


Please generalize and make that bit portable too.

Thanks,
Karel

On 6/25/22 15:00, Duc Doan wrote:

Hello Christian,

I forgot to send the sample code. Here it a code to turn on an LED:

/*/

// Obtain the pointer to the instance (port D)
rtems_gpio_ctrl_t *ctrl;
stm32f4_gpio_get_ctrl(GPIOD, );

// enable clocks for port D
rtems_gpio_initialize(ctrl);

// configure the pin
rtems_gpio_set_pin_mode(ctrl, _PIN, RTEMS_GPIO_PINMODE_OUTPUT_PP);
rtems_gpio_set_pull(ctrl, _PIN, RTEMS_GPIO_PULLUP);

// output to LED
rtems_gpio_write(ctrl, _PIN, RTEMS_GPIO_PIN_SET);

/*/

Best,

Duc Doan
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


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

2022-06-25 Thread Duc Doan
Hello Christian,

I forgot to send the sample code. Here it a code to turn on an LED:

/*/

// Obtain the pointer to the instance (port D)
rtems_gpio_ctrl_t *ctrl;
stm32f4_gpio_get_ctrl(GPIOD, );

// enable clocks for port D
rtems_gpio_initialize(ctrl);

// configure the pin
rtems_gpio_set_pin_mode(ctrl, _PIN, RTEMS_GPIO_PINMODE_OUTPUT_PP);
rtems_gpio_set_pull(ctrl, _PIN, RTEMS_GPIO_PULLUP);

// output to LED
rtems_gpio_write(ctrl, _PIN, RTEMS_GPIO_PIN_SET);

/*/

Best,

Duc Doan
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel


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

2022-06-25 Thread Duc Doan
Hello Christian,

On Fri, 2022-06-24 at 17:32 +0200, o...@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 

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(
  

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

2022-06-24 Thread oss

Hello Duc,

Am 24.06.22 um 16:28 schrieb Duc Doan:

Hello Christian,

On Thu, 2022-06-23 at 18:30 +0200, o...@c-mauderer.de wrote:

Another tricky part can be how to handle pins or pin groups. At the
moment I just used an "unsigned" for a single pin. That wouldn't be
able
to handle a pin group. Maybe a pin group needs it's own type or some
kind of extensible type. For the usual controller with <= 32 bit a
mask
in a uint32_t would be great. For other controllers maybe a longer
mask
is necessary. That's a bit tricky.


Thank you for the pseudocode, I think your method is better than mine.
I am currently rewriting the code. However, I am not clear about pin
groups: Is a "pin group" same as a "port"? Or does a group mean pins
from that group can come from different ports/GPIO controllers?


It's not unlikely that you want to change multiple pins on one 
controller at the same time. That's what I meant with "pin groups". On a 
controller level it would be (for most controllers):


- Read current value from output register into a temporary variable.
- Change the pins in the group to the new value in that temporary variable.
- Write back the new value to the output register.



Also, I am thinking that maybe I can create an opaque type for pin mask
that BSPs will implement, instead of a specific type like
uint32_t. That type could be used as a long mask or just a pin number,
depending on the BSP.


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.


Best regards

Christian



Best,

Duc Doan


___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-24 Thread Duc Doan
Hello Christian,

On Thu, 2022-06-23 at 18:30 +0200, o...@c-mauderer.de wrote:
> Another tricky part can be how to handle pins or pin groups. At the 
> moment I just used an "unsigned" for a single pin. That wouldn't be
> able 
> to handle a pin group. Maybe a pin group needs it's own type or some 
> kind of extensible type. For the usual controller with <= 32 bit a
> mask 
> in a uint32_t would be great. For other controllers maybe a longer
> mask 
> is necessary. That's a bit tricky.

Thank you for the pseudocode, I think your method is better than mine.
I am currently rewriting the code. However, I am not clear about pin
groups: Is a "pin group" same as a "port"? Or does a group mean pins
from that group can come from different ports/GPIO controllers?

Also, I am thinking that maybe I can create an opaque type for pin mask
that BSPs will implement, instead of a specific type like
uint32_t. That type could be used as a long mask or just a pin number,
depending on the BSP.

Best,

Duc Doan
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-23 Thread oss

Hello Duc,

Am 23.06.22 um 13:36 schrieb Duc Doan:

On Tue, 2022-06-21 at 17:23 +0200, o...@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.


Most controllers I've worked with use that organization but I'm not sure 
whether it's true for all controllers. Isn't the controller on the 
raspberry an example where there is only one big group of GPIO0 to 
GPIO<$BigNumber>?


But I think you can always organize pins in that way. Only make sure 
that you don't assume that every controller has a maximum of 32 pins. If 
there is only one GPIO controller on a system that has 400 pins, that 
shouldn't be a problem. The same is true if you have 400 controllers 
with one pin each. The logical structure works in both cases.


Note that not all controllers have to be the same type. See my notes 
below regarding the I2C GPIO chip.





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 

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

2022-06-23 Thread Duc Doan
On Tue, 2022-06-21 at 17:23 +0200, o...@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

> 


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

2022-06-21 Thread oss

Am 21.06.22 um 16:31 schrieb Duc Doan:

Using examples of working APIs is a good idea. But be careful not to
copy any code from that framework because the license (GPL) wouldn't be
compatible.


Sure, I don't copy their code but only see what functions should be in a 
GPIO API (like read, write, toggle, pinmode).


Is set and reset the only state a pin can have? Or is that field
thought
to be extended with (for example) open drain or similar states if a
device supports that?


I think it can be extended but I have only put in the most basic states 
for now.



Beneath that: Not a fan of SET == 0. I think RESET == 0 would be better
because than you can use it as a boolean without conversion.


You are right, that was my mistake. I have fixed it.

Does that mean it is (for example) a GPIO controller? In that case
maybe
call it "rtems_gpio_ctrl_t". My first guess from the name would have
been that it is already a pin.

I have made changes in my newest patch, and rtems_gpio_t is now 
essentially a pin.


Same is true for the structures below: How would I initialize one of
these objects in the application?


The example initialization of those structures can be found in my sample 
blink code: 
https://github.com/dtbpkmte/GSoC-2022-RTEMS-Sample-Apps/blob/main/RTEMS_Blink_API/src/init.c 
 


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.


I know that it is difficult in this case. On the one hand an API should 
be portable. On the other hand it should be able to handle very 
different hardware. And all that with the lowest possible overhead. In 
the end it will be some compromise.


Your goal is to either offer a better compromise than the API that is 
currently used for beagle and RPi. Or as an alternative: Don't try to go 
for an universal one and focus on your current device like a lot of the 
BSPs do. I would prefer a good universal API (better than the Beagle / 
RPi one (*)) but I know the problems so I could live with a device 
specific too. But note that this is my personal opinion. Others might 
have a different one.


(*) In case someone didn't see that (I think it was on discord): The 
Beagle / RPi API has two weaknesses in my point of view:


1. It mixes GPIO with Pinmuxing which is not true for all chips. For 
example the whole Freescale / NXP devices tend to have separate 
controllers for that. Having two APIs for that would be better in my 
point of view.


2. It is written with a quite fixed structure in mind. Controllers that 
don't have that structure need bigger workarounds which makes the API slow.


. The definition of the structures are defined by BSP. Here are 
STM32F4's definitions:

/* CODE BEGINS ***/
struct rtems_gpio_t {
     GPIO_TypeDef *port;
     uint16_t pin;
};

/**
   * This structure should be initialized to 0
   *
   * This structure holds configuration options for STM32F4-specific
   * GPIO. The 2 specific modes are Event and Alternate modes. Select
   * a mode by setting the correct field (is_event_mode or 
is_alternate_mode)

   * to 1.
   */
struct rtems_gpio_config_t {
     uint32_t speed;             /* Speed of the pin. Must be specified */

     uint32_t interrupt_mode;    /* The type of interrupt trigger of the 
pin

                                    Use if the pin is in Interrupt mode */

     uint32_t is_event_mode;     /* Sets to 1 if the pin is in event mode,
                                    0 other wise.
                                    Use if the pin is in Event mode */
     uint32_t event_mode;        /* The type of event trigger of the pin
                                    Use if the pin is in Event mode */

     uint32_t is_alternate_mode; /* Sets to 1 if the pin is in Alternate 
mode,

                                    0 other wise.
                                    Use if the pin is in Alternate mode */
     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 */
};
/* CODE ENDS ***/

What would be done in that function?

Why does the application has to implement it?

Where would it be called?


The initialize function is meant to perform setup code for the GPIO. For 
example, for the 

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

2022-06-21 Thread Duc Doan
>
> Using examples of working APIs is a good idea. But be careful not to
> copy any code from that framework because the license (GPL) wouldn't be
> compatible.


Sure, I don't copy their code but only see what functions should be in a
GPIO API (like read, write, toggle, pinmode).

Is set and reset the only state a pin can have? Or is that field thought
> to be extended with (for example) open drain or similar states if a
> device supports that?
>

I think it can be extended but I have only put in the most basic states for
now.


> Beneath that: Not a fan of SET == 0. I think RESET == 0 would be better
> because than you can use it as a boolean without conversion.
>

You are right, that was my mistake. I have fixed it.

Does that mean it is (for example) a GPIO controller? In that case maybe
> call it "rtems_gpio_ctrl_t". My first guess from the name would have
> been that it is already a pin.
>

I have made changes in my newest patch, and rtems_gpio_t is now essentially
a pin.

Same is true for the structures below: How would I initialize one of
> these objects in the application?
>

The example initialization of those structures can be found in my sample
blink code:
https://github.com/dtbpkmte/GSoC-2022-RTEMS-Sample-Apps/blob/main/RTEMS_Blink_API/src/init.c
. The definition of the structures are defined by BSP. Here are STM32F4's
definitions:
/* CODE BEGINS ***/
struct rtems_gpio_t {
GPIO_TypeDef *port;
uint16_t pin;
};

/**
  * This structure should be initialized to 0
  *
  * This structure holds configuration options for STM32F4-specific
  * GPIO. The 2 specific modes are Event and Alternate modes. Select
  * a mode by setting the correct field (is_event_mode or is_alternate_mode)
  * to 1.
  */
struct rtems_gpio_config_t {
uint32_t speed; /* Speed of the pin. Must be specified */

uint32_t interrupt_mode;/* The type of interrupt trigger of the pin
   Use if the pin is in Interrupt mode */

uint32_t is_event_mode; /* Sets to 1 if the pin is in event mode,
   0 other wise.
   Use if the pin is in Event mode */
uint32_t event_mode;/* The type of event trigger of the pin
   Use if the pin is in Event mode */

uint32_t is_alternate_mode; /* Sets to 1 if the pin is in Alternate
mode,
   0 other wise.
   Use if the pin is in Alternate mode */
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 */
};
/* CODE ENDS ***/

What would be done in that function?
>
> Why does the application has to implement it?
>
> Where would it be called?
>

The initialize function is meant to perform setup code for the GPIO. For
example, for the STM32, it would be enabling the clocks of the ports. The
application needs to implement it if they want to use GPIO because the
peripheral needs initialization. They don't have to, though, if they want
to do that initialization somewhere else. This function is called in
bsp_start(). It is already implemented as a weak, empty function, so there
is no problem if the user doesn't implement it.

What would be possible error cases? Is one "UNSATISFIED" enough or
> should it be able to return other errors too (like the return value from
> an I2C transfer because the pin is connected to some SPI-GPIO extender).


 I think "UNSATISFIED" is enough because these are quite low-level. I think
the return values from more complicated things like I2C should be handled
in other functions (like the I2C API), and I want to keep the GPIO thing
portable. I am open to more discussion though, because I am not sure I can
think of all use cases of this GPIO API.

If the write can fail, the read can also fail. Do we need an error
> return value too?
>

Yes, I think that's a good idea. I changed it as below:

/**
  * @brief Reads the digital value of a pin.
  *
  * @param[in] gpiox The GPIO object that owns the pin.
  *
  * @param[out] value The state of the pin.
  *
  * @retval RTEMS_SUCCESSFUL Pin succesfully read.
  * @retval RTEMS_UNSATISFIED Could not read pin.
  */
extern rtems_status_code rtems_gpio_read_pin(rtems_gpio_t *gpiox,
rtems_gpio_pin_state *value);

Best,

Duc Doan
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

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

2022-06-19 Thread oss

Hello Duc,

Am 14.06.22 um 16:46 schrieb Duc Doan:

Dear all,

I am proposing a new GPIO API for RTEMS. The current API is kind of tailored to 
some specific hardware and therefore may require some overhead to make it fit 
for others. The one I am proposing is not finished but it is aimed to be simple 
and generic. It has some opaque type structures that need to be implemented by 
BSP. The functions include initialization, configuration, reading, writing, and 
toggle. I took inspiration from the Wiring framework. I also have an example 
implementation for the STM32F4 BSP.


Using examples of working APIs is a good idea. But be careful not to 
copy any code from that framework because the license (GPL) wouldn't be 
compatible.




I would love to get feedback from all of you.

Thank you,

Duc Doan

---
  bsps/arm/stm32f4/gpio/gpio.c |  39 +++
  bsps/include/bsp/gpio2.h | 129 +++
  2 files changed, 168 insertions(+)
  create mode 100644 bsps/arm/stm32f4/gpio/gpio.c
  create mode 100644 bsps/include/bsp/gpio2.h

diff --git a/bsps/arm/stm32f4/gpio/gpio.c b/bsps/arm/stm32f4/gpio/gpio.c
new file mode 100644
index 00..40aea3febd
--- /dev/null
+++ b/bsps/arm/stm32f4/gpio/gpio.c
@@ -0,0 +1,39 @@
+#include 
+#include 
+#include 
+#include 
+
+struct rtems_gpio_t {
+GPIO_TypeDef *port;
+};
+
+struct rtems_gpio_pin_t {
+uint16_t pin_mask;
+};
+
+struct rtems_gpio_config_t {
+GPIO_InitTypeDef *config;
+}
+
+__weak rtems_status_code rtems_gpio_initialize(void) {
+return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_configure(rtems_gpio_t *gpiox, 
rtems_gpio_config_t *config) {
+HAL_GPIO_Init(gpiox->port, config->config);
+return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_write_pin(rtems_gpio_t *gpiox, rtems_gpio_pin_t 
*pin, rtems_gpio_pin_state value) {
+HAL_GPIO_WritePin(gpiox->port, pin->pin_mask, value);
+return RTEMS_SUCCESSFUL;
+}
+
+rtems_gpio_pin_state rtems_gpio_read_pin(rtems_gpio_t *gpiox, rtems_gpio_pin_t 
*pin) {
+return HAL_GPIO_ReadPin(gpiox->port, pin->pin_mask);
+}
+
+rtems_status_code rtems_gpio_toggle_pin(rtems_gpio_t *gpiox, rtems_gpio_pin_t 
*pin) {
+HAL_GPIO_TogglePin(gpiox->port, pin->pin_mask);
+return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/include/bsp/gpio2.h b/bsps/include/bsp/gpio2.h
new file mode 100644
index 00..ef10d1729a
--- /dev/null
+++ b/bsps/include/bsp/gpio2.h
@@ -0,0 +1,129 @@
+/**
+  * @file
+  *
+  * @ingroup rtems_gpio2
+  *
+  * @brief RTEMS GPIO new API definition.
+  */
+
+ /*
+  *  Copyright (c) 2022 Duc Doan 
+  *
+  *  The license and distribution terms for this file may be
+  *  found in the file LICENSE in this distribution or at
+  *  http://www.rtems.org/license/LICENSE.
+  */
+
+#ifndef LIBBSP_SHARED_GPIO2_H
+#define LIBBSP_SHARED_GPIO2_H
+
+#include 
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @name GPIO data structures
+ *
+ * @{
+ */
+
+/**
+  * @brief GPIO bit set and reset enumeration.
+  */
+typedef enum {
+RTEMS_GPIO_PIN_SET = 0,
+RTEMS_GPIO_PIN_RESET
+} rtems_gpio_pin_state;


Is set and reset the only state a pin can have? Or is that field thought 
to be extended with (for example) open drain or similar states if a 
device supports that?


Beneath that: Not a fan of SET == 0. I think RESET == 0 would be better 
because than you can use it as a boolean without conversion.



+
+/**
+  * @brief Opaque type for a GPIO object.
+  *To be implemented by BSP.
+  *
+  * @details This could represent the unit that owns GPIO pins.
+  *  For example, it would be a port for ARM Cortex-M.
+  */
+typedef struct rtems_gpio_t rtems_gpio_t;


Does that mean it is (for example) a GPIO controller? In that case maybe 
call it "rtems_gpio_ctrl_t". My first guess from the name would have 
been that it is already a pin.


I assume that you don't plan to publish the definition of the struct 
rtems_gpio_t, right? With that the application can only use pointers. 
Where does the application get the pointer from?


Same is true for the structures below: How would I initialize one of 
these objects in the application?



+
+/**
+  * @brief Opaque type for a GPIO pin object.
+  *To be implemented by BSP.
+  */
+typedef struct rtems_gpio_pin_t rtems_gpio_pin_t;
+
+/**
+  * @brief Opaque type for configuration of a GPIO object.
+  *To be implemented by BSP.
+  */
+typedef struct rtems_gpio_config_t;
+
+/** @} */
+
+/**
+  * @name GPIO Functions
+  *
+  * @{
+  */
+
+/**
+  * @brief Initialization for GPIO. To be implemented by User Application.
+  *
+  * @retval RTEMS_SUCCESSFUL GPIO successfully initialized.
+  * @retval RTEMS_UNSATISFIED Could not initialize GPIO object.
+  */
+extern rtems_status_code rtems_gpio_initialize(void);
+


What would be done in that function?

Why does the application has to implement it?

Where would it be called?


+/**
+  * @brief Configures a GPIO object.
+  

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

2022-06-14 Thread Duc Doan
Dear all,

I am proposing a new GPIO API for RTEMS. The current API is kind of tailored to 
some specific hardware and therefore may require some overhead to make it fit 
for others. The one I am proposing is not finished but it is aimed to be simple 
and generic. It has some opaque type structures that need to be implemented by 
BSP. The functions include initialization, configuration, reading, writing, and 
toggle. I took inspiration from the Wiring framework. I also have an example 
implementation for the STM32F4 BSP.

I would love to get feedback from all of you.

Thank you,

Duc Doan

---
 bsps/arm/stm32f4/gpio/gpio.c |  39 +++
 bsps/include/bsp/gpio2.h | 129 +++
 2 files changed, 168 insertions(+)
 create mode 100644 bsps/arm/stm32f4/gpio/gpio.c
 create mode 100644 bsps/include/bsp/gpio2.h

diff --git a/bsps/arm/stm32f4/gpio/gpio.c b/bsps/arm/stm32f4/gpio/gpio.c
new file mode 100644
index 00..40aea3febd
--- /dev/null
+++ b/bsps/arm/stm32f4/gpio/gpio.c
@@ -0,0 +1,39 @@
+#include 
+#include 
+#include 
+#include 
+
+struct rtems_gpio_t {
+GPIO_TypeDef *port;
+};
+
+struct rtems_gpio_pin_t {
+uint16_t pin_mask;  
+};
+
+struct rtems_gpio_config_t {
+GPIO_InitTypeDef *config;
+}
+
+__weak rtems_status_code rtems_gpio_initialize(void) {
+return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_configure(rtems_gpio_t *gpiox, 
rtems_gpio_config_t *config) {
+HAL_GPIO_Init(gpiox->port, config->config);
+return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_write_pin(rtems_gpio_t *gpiox, rtems_gpio_pin_t 
*pin, rtems_gpio_pin_state value) {
+HAL_GPIO_WritePin(gpiox->port, pin->pin_mask, value);
+return RTEMS_SUCCESSFUL;
+}
+
+rtems_gpio_pin_state rtems_gpio_read_pin(rtems_gpio_t *gpiox, rtems_gpio_pin_t 
*pin) {
+return HAL_GPIO_ReadPin(gpiox->port, pin->pin_mask);
+}
+
+rtems_status_code rtems_gpio_toggle_pin(rtems_gpio_t *gpiox, rtems_gpio_pin_t 
*pin) {
+HAL_GPIO_TogglePin(gpiox->port, pin->pin_mask);
+return RTEMS_SUCCESSFUL;
+}
diff --git a/bsps/include/bsp/gpio2.h b/bsps/include/bsp/gpio2.h
new file mode 100644
index 00..ef10d1729a
--- /dev/null
+++ b/bsps/include/bsp/gpio2.h
@@ -0,0 +1,129 @@
+/**
+  * @file
+  *
+  * @ingroup rtems_gpio2
+  *
+  * @brief RTEMS GPIO new API definition.
+  */
+
+ /*
+  *  Copyright (c) 2022 Duc Doan 
+  *
+  *  The license and distribution terms for this file may be
+  *  found in the file LICENSE in this distribution or at
+  *  http://www.rtems.org/license/LICENSE.
+  */
+
+#ifndef LIBBSP_SHARED_GPIO2_H
+#define LIBBSP_SHARED_GPIO2_H
+
+#include 
+#include 
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @name GPIO data structures
+ *
+ * @{
+ */
+
+/**
+  * @brief GPIO bit set and reset enumeration.
+  */
+typedef enum {
+RTEMS_GPIO_PIN_SET = 0,
+RTEMS_GPIO_PIN_RESET
+} rtems_gpio_pin_state;
+
+/**
+  * @brief Opaque type for a GPIO object.
+  *To be implemented by BSP.
+  * 
+  * @details This could represent the unit that owns GPIO pins. 
+  *  For example, it would be a port for ARM Cortex-M.
+  */
+typedef struct rtems_gpio_t rtems_gpio_t;
+
+/**
+  * @brief Opaque type for a GPIO pin object.
+  *To be implemented by BSP.
+  */
+typedef struct rtems_gpio_pin_t rtems_gpio_pin_t;
+
+/**
+  * @brief Opaque type for configuration of a GPIO object.
+  *To be implemented by BSP.
+  */
+typedef struct rtems_gpio_config_t;
+
+/** @} */
+
+/**
+  * @name GPIO Functions
+  *
+  * @{
+  */
+
+/**
+  * @brief Initialization for GPIO. To be implemented by User Application.
+  *
+  * @retval RTEMS_SUCCESSFUL GPIO successfully initialized.
+  * @retval RTEMS_UNSATISFIED Could not initialize GPIO object.
+  */
+extern rtems_status_code rtems_gpio_initialize(void);
+
+/**
+  * @brief Configures a GPIO object.
+  *To be implemented by BSP.
+  *
+  * @param[in] gpiox The GPIO object to be configured.
+  * @param[in] config The GPIO configuration object.
+  *
+  * @retval RTEMS_SUCCESSFUL GPIO configured successfully.
+  * @retval RTEMS_UNSATISFIED Could not configure GPIO object.
+  */
+extern rtems_status_code rtems_gpio_configure(rtems_gpio_t *gpiox, 
rtems_gpio_config_t *config);
+
+/**
+  * @brief Writes a digital value to a pin/pins.
+  *
+  * @param[in] gpiox The GPIO object that owns the pin(s).
+  * @param[in] pin The GPIO pin number or pin mask to be written.
+  * @param[in] value The state to be written to the pin(s).
+  *
+  * @retval RTEMS_SUCCESSFUL Pin successfully written.
+  * @retval RTEMS_UNSATISFIED Could not write to pin(s).
+  */
+extern rtems_status_code rtems_gpio_write_pin(rtems_gpio_t *gpiox, 
rtems_gpio_pin_t *pin, rtems_gpio_pin_state value);
+
+/**
+  * @brief Reads the digital value of a pin/pins.
+  *
+  * @param[in] gpiox The GPIO object that owns the pin(s).
+  * @param[in] pin The GPIO pin(s) to be read.
+  *
+  * @retval The state of the pin(s).
+  */
+extern