[En-Nut-Discussion] Nut/OS GPIO API Initial Design and Current Status
Ulrich Prinz
ulrich.prinz at googlemail.com
Sun Oct 14 18:55:07 CEST 2012
Hi again,
Am 14.10.2012 13:50, schrieb Harald Kipp:
> Hi Ulrich,
>
> On 12.10.2012 22:20, Ulrich Prinz wrote:
>> I am still very deep in other things, far away from Nut/OS but I asked
>
> It's really nice to see, that many developers keep in touch, although
> there current focus is somewhere else.
>
Nut/OS is always fun, whatever you do actually.
>
>> 2) To assign numbers to things that obviously are not related to any
>> mathematical predictable rule always causes software overhead in sort of
>> tables, switch cases, if then else...
>
> An index? X1 = 5 * Y2? Where is the mathematical rule of indices 1 and 2?
>
No, what I had min mind was, that you often can address ports in ARM by
just having a base address and add a fixed multiple of the port number
to get the right address. Like 0x2006000 + (port * 0x2000).
On AVR and other smaller chips you may have ports A..D at 0x120 + (port
* 0x04) but as the family grew bigger and the bit addressable area
didn't grew too, PORTE...PORTH where thrown somewhere else around the
memory.
>
>
>> Independent of any chip or CPU, NutGetPin/Port(NUT_GPIO_PORTx, bit) must
>> give the value of the bit at that port.
>
> That's the idea.
>
>> As you mentioned the extra features are a problem as different chips do
>> provide different optional features. I already proposed there something
>> but only Thiago ever tried to follow that thing. The idea was to make
>> some some commonly used options as a standard and to allow integrators
>> to add more.
>
> That's the point. Why do you want to add more features? Where is the
> advantage?
>
As speed rises, you'll be more and more in the need to debounce, set
precise pull-ups or pull-downs and so on.
> If an MCU family provides specific features like debouncing or repeater
> mode, a native API tailored for this specific family would be sufficient.
>
> For AVR we have avr/io.h from avr-libc. For NXP we may create nxp-iolib
> with nxp/io.h. GpioXXX currently uses avr-libc to implement the required
> functions. When ported to NXP, GpioXXX could have used nxp-iolib likewise.
>
> If I write a driver specifically for the AVR, I'd _not_ use GpioXXX.
> Instead I'd use the non-portable avr-libc API, because my AVR specific
> driver doesn't need to be portable.
>
> And this is the point where I'm still missing an answer:
>
> Why the hell is the portable Gpio API used for drivers, which are not
> portable themselves?
Ok, that I forgot to answer precisely:
1)
Q) Why general function set for GPIO access, not a special one for
high-level and low-level programming?
A) For STM32 there is no need to use separate APIs for GPIO as the API
functions are already the fastest way to access GPIO. So there is only
one function set available.
2)
Q) Why do I feel that a separate GPIO access is obsolete?
A) If you are porting a new chip, you might think that you need
comfortable and easy access GPIO functions and you know that the AVR
example is the easiest one to understand. But then, with the first RS485
driver, where you have to switch bus direction using your own GPIO
access functions, you learn that GPIO access times might be relevant to
system performance. So you do the work, you should have done at the
beginning, just a little bit later.
And at the end you ask yourself, why should I use a fast method to
switch and control GPIOs in my low-level drivers, but only provide a
complicated slow code to the API users?
3)
Q) Why should I try to provide access to all features a chips component has?
A1) Because I could.
A2) Because there is always one person needing exactly that thing that
you thought of as obsolete.
A3) It doesn't hurt, as here the same things apply that apply for the
GPIO access functions. Normally small chips just have little features
for their GPIOs (and their other peripherals too). So a small value is
enough for their features. I.e. for AVR a size_t or uint8_t should be
fine and all options could be addressed.
In one case NUTGPIO_PULLUP is 0x02, in the other case it is 0x00020030
or even ((1<<PUE) | (1<<XEN) | (2<<PURES))
What should be unified is the name of the option. And if you compile a
project that uses a feature that your chip doesn't provide, it should
result in an error as the features are defined per chip.
>
>
>> And if a board really doesn't support any kind of LED you could assign
>> the LED pins to some unused GPIOs, so it doesn't hurt the demo with lots
>> of #ifdef...#endif.
>
> I also see this requirement, but think, that this is related to Ole's
> topic about GPIO configuration.
>
No that is the point I am talking of:
You have the problem that making demo-code is difficult as the chips
provide too much different options to do some basic things. And then, to
top all that, the boards provide different peripherals connected to
different pins too.
The solution is:
1) Handle as much as possible interfaces in drivers.
2) Make drivers for chips clients of drivers for busses.
3) Create a chips specific init, followed by a board specific init.
4) In your main loop only devices exist.
So:
1) I created a fast GPIO access function
2) I created a Key and LED device using 1)
3) In the board.c I configure a GPIO as output, what automatically
enables clocks and things for the GPIO system. Then I register a LED
connected to that GPIO by using my driver.
4) In demo main() I just set the behavior of the LED and it blinks.
As a low level programmer or someone who ports a chip, you have just to
provide 1) and 3) and the demo code provided by 4) will work out of the box.
As a API user that uses a different board, you copy the board file,
change the needed GPIO pins to the ones matching your board, and the
code again runs.
GPIO is just an example. If you can register an I2C bus that provides
the Nut/OS compliant acccess functions, you can always register an
EEPROM on top of that bus and it will work.
So making demo code for EEPROM is as easy as let an LED blink.
Last one:
Never try to handle multiple boards with one board.c file. It will end
in unreadable code that any new user will not understand.
This could be done in a project you develop for your company where
anyone involved knows what you do. But it doesn't help anyone else.
Ulrich
More information about the En-Nut-Discussion
mailing list