[En-Nut-Discussion] Unified GPIO implementation

Ulrich Prinz uprinz2 at netscape.net
Wed Oct 6 21:00:08 CEST 2010



Am 06.10.2010 20:45, schrieb Thiago A. Corrêa:
> Hi,
>
> 2010/10/6 Harald Kipp<harald.kipp at egnite.de>:
>> On 06.10.2010 07:29, Thiago A. Corręa wrote:
>>> 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)
>>>
>>>      Why not define it as simply int8_t GpioPinConfigSet( uint8_t port,
>>> uint8_t pin, uint8_t cfg) for all architectures?
>>
>> The compiler will generate additional code for 32-bitters with uint8_t
>> arguments to clear the upper bytes of the register. I'd recommend to use
>> uint_fast8_t. See
>
> Ah, ok.
>
> We already define ureg_t in sys/types.h, it fits perfectly for this:
>
> ureg_t GpioPinConfigSet( ureg_t port, ureg_t pin, ureg_t cfg )
> where ureg_t is usually sizeof(register)
>
What doesn't work for Cortex as registers might be uint16_t and uint32_t.

> Then we can have just one include file that defines the function
> signature instead of one for each architecture.
>
>> But the return value caught my attention:
>>
>> int8_t function();
>>
>> IMHO won't help 8-bitters. AFAIK, functions always must return at least
>> 2 bytes on the AVR. Simply because C allows to call unknown functions.
>> Such functions are expected to return an integer value.
>
> For AVR32 it makes sense to use a return type that is the same size of
> the register, as it's usually stored in R12.
> Or it could simply return void.

For Cortex it doesn't matter as half-word operation is as fast as word 
operation. And Cortex does unaligned addressing without speed impact.

>
> [...]
> Ok, can we change this in trunk already then?
>
>>> There is also one area that is not covered in the document. The
>>> AVR32 toolchain defines which references the GPIO set their values as
>>> pin numbers, not ports/pins. So, some sort of conversion macro is
>>> needed, to use that convention with the port/pin convention in Nut/OS.
>>
>> I think Michael Fischer already implemented such a macro. In general it
>> is not a bad idea to use pin numbers only. It would save one parameter
>> in the function call.
>>
>
> I think we discussed that a while ago and decided to go with the
> Port/Pin pair. Really it doesn't make too much of a difference, but
> for avr 8 bit it might confuse the users who is acostumed with
> ports/pins.
> Even though AVR32 toolchain use PIN only in it's defines, the
> datasheet does mention ports/pins
>

If you see a high performance improvement by using this, you can add 
this functionality for AVR32 only.

That's what I told you in th other thread:

We define a mandatory set of functions and defines and we allow 
architecture specific optional functions and defines. With the non debug 
compiler settings this doesn't matter as if you don't use a function it 
will not be in the compiled code.

> I had a macro to do it the other way around: convert pin to port/pin.
> I think it was later removed.
>
I already added some functions like that in the STM32 API. Cause I had 
to get from Nut/OS naming to STM32 and back. But I am not sure if I 
still need them in the latest code.
>
> About the alternate functions to be configurable by Nut/OS. I'm
> already doing it for AVR32. My board uses the alternative2 pins for
> the usart.
> Here is where I'm at right now:
> Nutconf enumerated type requires a macro to define a different macro,
> ie, it generates this:
> #ifndef UART2_ALT_PINSET
> #define UART2_ALT_PINSET ALTERNATE2
> #endif
>
> for the following entry in avr32.nut:
> {
>      macro = "UART2_ALT_PINSET",
>      brief = "USART2 Alternative Pinset",
>      type = "enumerated",
>      choices = function() return GetAlternativePinsets() end,
>      flavor = "booldata",
>      file = "include/cfg/uart.h"
> },
>
That's the same what I do for STM32. Exactly the same. But the STMs have 
up to 3 or 4 different alternate settings on some peripherals :)

> I thought about instead of ALTERNATE2, reuse the GPIO_CFG_PERIPHERAL0
> which is already defined. But it might be a bit confusing to see that
> in the Nutconf. Should we just define a new set of macros for the
> config? Something along the lines of:
>
> #define ALTERNATE_PIN1  1
> ...
> #define ALTERNATE_PINn  n

I don't like this idea as I prefer to keep data sheet naming aligned to 
code naming. The STM32 talks about alternate function and so do I.

By the way, with STM32 it is configured the other way round.
There are GPIO control and data registers.
There are peripherals registers and then there is the AFIO in the 
middle, the Alternate Function Input Output Controller that routes the 
peripherals to the pins as selected.

So you have only one option for the gpio, it is connected to gpio or 
peripheral. Someone else decides which of the peripherals use the pin.

For keeping the things easy I decided to put the AFIO control to the 
xxxInit() function. So the UsartInit() sets up the correct pins, given 
as parameter from nutconf. This is transparent for the user and does not 
introduce new GPIO functions that none of the other architectures 
support. And it does not add a single byte of code as all is handled by 
the preprocessor.

Best regards
Ulrich



More information about the En-Nut-Discussion mailing list