[En-Nut-Discussion] Unified GPIO implementation
Duane ellis
ethernut at duaneellis.com
Sun Oct 10 02:07:15 CEST 2010
On 10/6/2010 1:29 AM, Thiago A. Corrêa wrote:
> About the GPIO Architecture Specific section, it's suggested to
> use different function signatures for different archtectures, whether
> they are 8 bit or 32 bits. It's suggested:
>
> AVR:
> int8_t GpioPinConfigSet( uint8_t port, uint8_t pin, uint8_t cfg)
>
> AVR32,ARM,Cortex
> int GpioPinConfigSet( uint32_t port, uint32_t pin, uint32_t cfg)
>
(a) Use "int" - as the gpio id - and nothing else.
Use "int' as the configuration
Use "int' as the value
Int is the natural size of the machine, and is naturally fast.
if you *insist* - then create an ARCH specific typedef - like this:
#if !defined(GPIO_ID_TYPEDEFFED)
#define GPIO_ID_TYPEDEFFED 1
// default is an int type
typedef int GPIO_ID;
#endif
(b) Use "-1" as invalid, for example some chips have built in USB
resistors, others have the USB resistor external
You need a simple "invalid" - here's why: Example USB - some
controllers have a built in "attach" resistor some use a GPIO pin ...
you must be able to #define USB_GPIO_RESISTOR as "invalid" - thus you
can can specify
// Port C, Bit 4 - is the usb resistor
#define USB_GPIO_RESISTOR_PIN MAKE_GPIO_ID( PORT_ID_C, 4 )
OR
#define USB_GPIO_RESISTOR_PIN GPIO_ID_INVALID
(d) Don't worry about "signed" numbers here - signed numbers are just
fine, reason:
most 8bit chips very few gpio pins... (ie: less then 64) - an INT
works
most 16bit machines - have a few more - but still not many - an INT
works
Most 32bit machines - no chip has 2billion pins - an INT works.
Also - LESS THEN 0 tests are simple and fast on nearly all machines.
(d) Often generic code needs a GPIO as a function...
If the gpio operation is a function - it costs *MORE* in code and
*CLOCK*CYCLES* to (a) loading two values into two parameter registers,
(b) passing these through a *MULTIPLE* few layers of boiler plate code,
and you also have configuration values in structures and #defines.
(e) It is easy to create a macro (Each arch/chip makes its own)
#define MAKE_GPIO_ID( PORT_NUM, BIT_NUM ) ((PORTNUM * BITSPER_PORT)
+ BIT_NUM)
#define GPIO_ID_INVALID (-1)
(d) That SHIFT/MASK can be *UNDONE* in a macro
GPIO_GET_PORT_NUM( ID ) ((ID) / BITSPERPORT)
GPIO_GET_PORT_BITNUM(ID) ((ID) % BITSPERPORT)
Because BITSPERPORT - is a constant, and is a power of 2 - the compiler
turns these into SHIFT or AND operations, can't get much faster then
that, no need to optimize...
> The AVR32 toolchain defines which references the GPIO set their values as
> pin numbers, not ports/pins. [snip]
>
> #define AVR32_USART2_RXD_0_PIN 33
> Which would translate to port B, pin 1.
Exactly my point - simple macros {I presume this is what they are doing,
I don't have the docs in front of me}
#define GPIO_PORT_NUM( ID ) ( ID / 32 )
#define GPIO_PIN_NUM(ID) (ID % 32)
#define GPIO_PIN_MASK(ID) (1 << (ID % 32))
-Duane.
More information about the En-Nut-Discussion
mailing list