[En-Nut-Discussion] Nut/OS GPIO API Initial Design and Current Status
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
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