[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