[En-Nut-Discussion] Nut/OS GPIO API Initial Design and Current Status

Ulrich Prinz ulrich.prinz at googlemail.com
Sat Oct 13 15:17:24 CEST 2012

Am 13.10.2012 00:08, schrieb Uwe Bonnes:
>>>>>> "Harald" == Harald Kipp <harald.kipp at egnite.de> writes:
> ...

> Well, I have a bitbanging debug driver under my fingers. This will allow to
> use the STM32F4 discovery boards nearly self-contained, after reflashing the
> original ST-LINK with the "Blackmagic Debug Probe" code. It uses the Gpio
> Api and at the moment the CM3 systick for timing. So it will work not only
> for STM32 but any CM3 arch.
That was one reason for me to read the different manuals carefully that 
explain how to use the bitbend area of CortexM chips. Then I took some 
nights of deep and healthy sleep and then I wrote the NutGpio*Set/Get 
functions as only #define abstractions.
Now they are atomic and they are as fast as possible as they most times 
only produce one line of assembler.

But I didn't track if they made it into the current Nut/OS. We use them 
a lot in our firmware.

>      Harald> Suddenly users demand to implement all these special functions,
>      Harald> that their target chip provides. Enabling pull-ups or switching
>      Harald> from push/pull to open drain are the most harmless variants
>      Harald> (which btw. would have been required by an I2C driver
>      Harald> anyway). Other, less harmless extensions were debouncing,
>      Harald> repeater mode and other exotic stuff.  Instead of one simple
>      Harald> dev/gpio.h and its related implementations arch/arm/at91_gpio.c,
>      Harald> arch/avr/gpio.c etc. we now have several headers, and a growing
>      Harald> number of features. This makes it harder and harder for newbies
>      Harald> to implement GPIO on a new platform. The initial idea was
>      Harald> spoiled.
> I don't agree with your view. Each architecture needs a setup for it's GPIO,
> and this setup is getting more complicated as chips get more
> compilcated. This results in more available feature, but many features are
> only features, nice things to have, but not nescessary for general examples.
> This is where my plea from July for a definition of a common subset for
> features, defined in include/dev/gpio.h came from. Other architecture
> specific features can then be defined in the dev/gpio_<arch>.h files. But
> other architecture must know what to do if they find such a feature
> request. Is it really a request or a requirement? Should they fail in
> GpioPinConfigSet or should they ignore the request? That we need to agree
> about.

I daub that you need a complicated, all featured GPIO driver that covers 
any available option...

GPIOs are only helpers to get or do something.

For beginners that like to let a LED blink, it doesn't matter if it 
takes 5ns or 1ms. But it is easy for them to use NutGpioPinSet( PORT0, 1);

If you are an advanced programmer you think of and write drivers. So if 
there is a driver for an SPI EEPROM, it makes a difference if your 
chip-select is 1ms or 10ns as it makes a difference if you can read 
10k/s or 10M/s. But then you are an advanced programmer and you are 
programming a driver that hides all these nifty tricks from the beginner 
or simple API user.
The API user just calls NutSpiRegisterEeprom( Bus, PORT2, PIN5) and 
doesn't care how you flip the gpio.

It is fine, if your nutgpio() is as fast as the tricky dirty driver used 
far deep down in the lower levels, and if it is easy to do, it should be 
done. But it is not needed.

>      Harald> Now the fun really begins: The GPIO API is mainly used by target
>      Harald> specific drivers. Why, the hell, do target specific drivers
>      Harald> prefer the bulky and slow GPIO API, instead of using native port

It doesn't have to be and it isn't bulky slow with STM32...
But if you split optimized gpio access functions for different 
architectures, you have to duplicate many drivers that now work for all 

I.e. SPI EEPROM will not work with AT91SAMx as it supports hard wired 
chip select, while STM32 doesn't support chip select like AVR does.

>      Harald> access? My assumption is, that this was motivated by the
>      Harald> configuration feature. The Nut/OS Configurator offers to define
>      Harald> banks in a user friendly way, depending on the current target as
>      Harald> PORTA on Atmel chips or PORT0 on NXP chips. So using GpioPinXX()
>      Harald> allows to (ab-)use this feature.
> Or you view it another way: GPIO API offers such a flexible way that
> using it was the most straightforward thing.
>      Harald> Of course, developer's recognized, that GpioPinXX() was bulky
>      Harald> and slow.  To overcome this limitation, target specific inline
>      Harald> versions had been created to replace the original
>      Harald> versions. IMHO, that's the final stab.
>      Harald> GPIO API, REST IN PIECE. ;-)
> I hope, I oversee the smiley.
> My work on the AVR showed, that even for that arch you could defined the
> GpioApi in a way that will result in most cases in the single commands sbi()
> and cbi() as would unportable direct coding. And even
> the bank argument as a runtime variable can be handled without a big runtime
> switch case but by a pointer access if you look at the three consecutive AVR
> port/pin/ddr register as a structure.
>      Harald> Now I'm really coming to an end. Just a few seconds...
>      Harald> A few target specific drivers use a different approach to avoid
>      Harald> the GPIO API and still provide configuration capabilities. They
>      Harald> are based on macros and include/cfg/arch/porttran.h. And they
>      Harald> are very tricky to implement, difficult to use and result in
>      Harald> ugly, hard to follow code.  Beside that, they use PIO IDs, not
>      Harald> port banks.
> Seems like a lot of code has not been touched for ages. Does it really work
> still ? Has anybody tested?
Never saw this porttran.h but will have a look at it.

I think about making my own ethernet/USB CANopen debug dongle, so why 
not with Nut/OS 5?

> At the moment AVR and STM32 make the most use of it. Other architecture need
> some work. Let's start after the  5.x release to get things straight.
You have to see, that STM32 was a one man show and nobody gave any 
complaint. So I had the option just to do it as I guess was the best 
way. But as I had to implement it in a way that my colleagues could use 
it, I always had the old Nut/OS API in mind. So I always felt the need 
to keep the upper layer intact.
So I decided to accept heavy tricky code (mostly chains of #defines) 
down under to keep things lightning fast and same time easy to use as 
names of functions and enums didn't change.

And it doesn't matter if there is header file that defines PORTA...PORTG 
and later PORT0...PORT11. Who cares if a new user can start his code by 
writing the names from the datasheet of the chip or the printed names on 
the demo circuit board?

It is the work of us low lever driver writers to make this possible.


More information about the En-Nut-Discussion mailing list