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

Ole Reinhardt ole.reinhardt at embedded-it.de
Mon Oct 15 18:33:31 CEST 2012


Hi all,

> Why do you think that GpioPinSetLow takes an additional read cycle? With
> Bit0 '0' writen to the Bitbanding address the bit is reset, with '1' ist is
> set.
> 
> But here we are at the internal implementation of GPIO for the STM32
> platform. Isn't that independant of the Ethernut GPIO Api? Do yu care if
> setting a pin in the bitbanging drivers is a tick slower on one platform
> then it could be hand-coded in a non-portable way?

With all the discussion about the bitbanding: Have you ever checked if
the bitband access for your CPU does exactly what you expect?

I ask as I had big problems on the LCP with the bitband access to the
GPIO pins:

I implemented GpioPinSetxxx set exactly the same way as it is done for
STM32 using bitbanding.

Now calling:

GpioPinSetHigh(NUTGPIO_PORT0, 1); 
GpioPinSetHigh(NUTGPIO_PORT0, 2); 

Result:

Only Pin 2 is set, pin1 did not change.

I discussed this with some NXP engeneers and they explained this as a
problem with the bitband statemachine. Internally you still have a
read-modify-write operation to the same register where each opration
takes a few CPU cycles. These two accesses are now translated in two
such read-modify-write operations, but they run more or less in parallel
and therefore it is translated to something like this:

state = read_state(port0)
state |= pin1
state = read_state(port0)
write_state(port0, state)
state |= pin2
write_state(port0, state)

So this is a race condition internally.

In fact, if you write:

GpioPinSetHigh(NUTGPIO_PORT0, 1); 
_NOP(); _NOP();
GpioPinSetHigh(NUTGPIO_PORT0, 2); 
_NOP(); _NOP();

everything works as expected.

So at last, I decided not to use bitband access for the GPIO pins.

I know, this issue will most probably be an issue of the LPC CPUs, but
perhaps you should check this for STM32 as well.

> We can argue about the Macros I introduced, the names are sub-otipmal. But
> still I don't see the advantage of writing "BB_PERIPH(&GPIOB->ODR,
> I2CBUS1_SDA_PIN) = 1;" or something similar against GpioPinSetLow(port, pin). 

I think it is fully ok to use the API in places where you don't need
high performance pin I/O. Using the API reads much easier than the
register access, but as mentioned before, I would try to use as less
dependencies to the GPIO API as possible and try to configure the I/O
port settings in the board file.

>     Harald> Sorry, that was a serious question, not a didactic question. I'm
>     Harald> just curious, if you intend to implement GPIO_PinAFConfig
>     Harald> features into GpioPinConfigSet to make it more portable.
> 
> Ulrich's proposal intended to do so. The STM32 gpio usage doesn't do that at
> the moment, neither does LPC. avr32/dev/pwm.c puts the argument for the pin
> configuration in the flags, that's the only file i see such a use.
> I can do so for STM32 too, I am totally unbiased in that regard.

On the LPC I'm using it like this:

GpioPinConfigSet(SD_SDIO_PORT_0, SD_CMD_PIN,    GPIO_CFG_PERIPHERAL2 |
GPIO_CFG_PULLUP);    // SD_CMD

> But if we ever see the alternate function setting in platform independant
> code, there is something wrong.

Yes, this code should only be used by the board files or platform
depending application code.

Bye,

Ole


-- 

Thermotemp GmbH, Embedded-IT

Embedded Hard-/ Software and Open Source Development, 
Integration and Consulting

http://www.embedded-it.de

Geschäftsstelle Siegen - Steinstraße 67 - D-57072 Siegen - 
tel +49 (0)271 5513597, +49 (0)271-73681 - fax +49 (0)271 736 97

Hauptsitz - Hademarscher Weg 7 - 13503 Berlin
Tel +49 (0)30 4315205 - Fax +49 (0)30 43665002
Geschäftsführer: Jörg Friedrichs, Ole Reinhardt
Handelsregister Berlin Charlottenburg HRB 45978 UstID DE 156329280 



More information about the En-Nut-Discussion mailing list