RTEMS GPIO API
andre.lousa.marques at gmail.com
Sun Jun 21 23:04:08 UTC 2015
On 16-06-2015 17:54, Gedare Bloom wrote:
> On Tue, Jun 16, 2015 at 8:14 AM, André Marques
> <andre.lousa.marques at gmail.com> wrote:
>> Hello ,
>> Thank you for the responses. Sorry for the late response and lengthy mail.
>> At this point the features mentioned in the blog post are almost done in the
>> code (apart from some details). There are some differences from what is
>> mentioned in the blog, but the overall idea still stands (an blog update is
>> in order, as well as more documentation in the code).
>> One major change is related with the interaction with the API. It currently
>> maintains a data structure which holds the current GPIO status (which pins
>> are used, what interrupt handlers they have associated, ...), so an
>> application can either fill a different structure to configure a pin, which
>> is passed to the API through an API call, or configure the pin directly
>> through API calls.
>> The struct approach can be used either to define a new pin to be requested,
>> or to update its configuration, all done by updating/changing the struct and
>> doing the same function call to the API. Since the structs can be defined on
>> a separate file, the application code can be the same across different
>> platforms, as the only diference is the configuration file that is
>> used/called. The platform specific configuration (which pin in y platform
>> corresponds to the warning led?) for an application would then be reduced to
>> file management.
>> The API call that does the processing of these structs parses them and does
>> the necessary API calls to setup/update the GPIO hardware as needed.
>> By having both a struct based interface and direct API call options an user
>> can choose what is best for their need. The direct API calls can be
>> specially useful for an interactive usage, through a shell program.
>> The current implementation for the above can be seen in ,  and .
>> Note that the gpio.c and gpio.h can be anywhere else at this point, as they
>> do not have any rpi code anymore (another question is where they could go
> I think the first place to migrate shared code is libbsp/shared. After
> that, we can consider whether the code is generic enough to put in
> cpukit, which is where other driver frameworks (i2c, libdrvmgr) have
> landed recently.
I have moved it to libbsp/shared, and at this point I think we can start
the code review process. I have cleaned the code and updated the doxygen
and comments, should I post a patch here in two parts (one for the
generic API, and other for the RPI implementation) for review, or should
it be done in github?
>> A pending issue is related with pin definitions. It would be useful if after
>> the pin request to the API, the application could have a gpio_pin_id which
>> would be used as a reference to an application pin.
>> Small example with direct API call:
>> gpio_pin_id warning_led;
>> gpio_request_pin(RPI_GPIO_23, &warning_led, DIGITAL_OUT, ..);
>> The RPI_GPIO_23 would be the platform pin number (the API calculates the
>> bank and pin number from this), but after the request the application uses
>> the gpio_pin_id to refer to it. The gpio_pin_id would be a simple struct
>> filled by the API with the calculated bank and pin numbers, which no one
>> else is supposed (or have the need to) to modify/use this struct other than
>> to pass it to the API to refer to a pin. This would also avoid the constant
>> bank/pin numbers calculation and pin number boundary validation that is made
>> currenty in every API call.
> That makes sense. You could define an opaque type to store the
> identifier. However, if it is a struct, passing it by value could be
> an expensive operation, so care should be taken there. (If you can fit
> it in 32-bits, you can union the gpio_pin_id with a uint32_t)
I left this out for the moment.
>> A final note would be the need for multiple pin operations. The rpi and most
>> platforms (I suppose) allow several pins to be defined on a single call, by
>> writting a more complete bitmask to the registers. This could be a challenge
>> with the struct approach (maybe by having pin arrays, instead of a single
>> pin in the struct, if they all share the same configuration). As for direct
>> pin calls maybe through variadic functions.
> I just got done writing about zero-length arrays for Yang Qiao
> but perhaps you could use something similar albeit simpler in this
> case too. You define the pin as a zero-length array (it should always
> be at least 1 though), and then include the number of pins in the
>>  -
>>  -
>>  -
>> --André Marques.
>> On 11-06-2015 15:13, Gedare Bloom wrote:
>>> On Wed, Jun 10, 2015 at 7:09 PM, Chris Johns <chrisj at rtems.org> wrote:
>>>> On 11/06/2015 3:01 am, Gedare Bloom wrote:
>>>>> On Mon, Jun 8, 2015 at 5:44 AM, André Marques
>>>>> <andre.lousa.marques at gmail.com> wrote:
>>>>>> I have just updated my GSOC blog  with a detailed post about how a
>>>>>> rtems-wide GPIO API could look like, and at the same time exposing the
>>>>>> current features of the Raspberry Pi GPIO API and how it can evolve to
>>>>>> I tried to make it as generic and flexible as possible, but that can be
>>>>>> with the number of platforms where rtems can be used. Api and method
>>>>>> were somewhat overlooked, as well as the definition of possible error
>>>>>> since I am not sure if it would be correct to have a set of error codes
>>>>>> this API, or if it should use rtems_status_code, or other.
>>>>>> Current code for the Raspberry Pi GPIO API can be looked at in ,
>>>>>> where I
>>>>>> am currently carving out the rpi specific code.
>>>>>> I tried to be as clear as possible in the blog, and now I would like to
>>>>>> any interested party to have a look and hopefully point failure points
>>>>>> suggestions, or ask for clarifications. It would also be interesting to
>>>>>> the community expectations towards an API such as this one.
>>>>> Great write-up.
>>>> I agree, it is a nice write up.
>>>>> Here are some comments/questions:
>>>>> - The "user application must fill a gpio_pin struct for every pin it
>>>>> needs" should probably be done through some set of API calls that help
>>>>> filling out that struct. I'd imagine some alloc with initialization,
>>>>> and dealloc, with most of the complexity in alloc/init.
>>>> Being const lets you fill them out when coding as a table which I have
>>>> found easy to review plus being const has the advantage on small RAM
>>>> devices of only using ROM type storage which they usually have more of.
>>>> I think an API to fill the struct in would be confusing and so think at
>>>> this point in time we should limit what we do.
>>> OK that is fair. On the other hand, anything we can do to make the
>>> const initializer easier would be good. I especially was concerned by
>>> #ifdef's inside the initializer.
>>>> I currently have 3 Zynq variants with similar IO requirements with very
>>>> different pin selections due to easier PCB routing and I have a separate
>>>> C file with pin definitions per variant. The resulting user code is
>>>> clean and simple.
>>> That makes much more sense, where the struct definition will be pulled
>>> in through the build system logic to choose the correct file to
>>>>> - The bsp_specific pointer might be better implemented with a
>>>>> zero-length array
>>>>> [https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html]. Since you embed
>>>>> the type of the struct, you can tell whether that array should have
>>>>> any data in it or not.
>>>>> - I wonder if eventually we can refactor all this to work with the
>>>>> libdrvmgr. This is a long-term question but might be one worth
>>>>> thinking about now. (libdrvmgr mainly focuses on providing
>>>>> abstractions for device drivers that attached to bus-based i/o
>>>>> protocols. You may like to take a look at its documentation.)
>>>> I have not looked at that API so I cannot comment but I wonder if this
>>>> is outside the scope of this GSoC project.
>>> Definitely outside the scope.
>> devel mailing list
>> devel at rtems.org
More information about the devel