[En-Nut-Discussion] Nut/OS GPIO API Initial Design and Current Status
ulrich.prinz at googlemail.com
Thu Oct 18 00:13:08 CEST 2012
Am 15.10.2012 17:55, schrieb Uwe Bonnes:
>>>>>> "Harald" == Harald Kipp <harald.kipp at egnite.de> writes:
> Harald> Hi Uwe, On 15.10.2012 10:53, Uwe Bonnes wrote:
>>>>>>>> "Harald" == Harald Kipp <harald.kipp at egnite.de>
> Harald> I disagree, for example, with Harald>
> arch\cm3\dev\stm\stm32_twi1.c. This is STM32 specific code and
> Harald> don't need to use the portable Gpio API.
>>> Huch, what should I do else? Write "CM3BBREG(I2C_PORT,
>>> GPIO_Typedef, BSRR, 1<<(I2CBUS1_SDA_PIN+16))" instead of
>>> "GpioPinSetLow( I2C_PORT, I2CBUS1_SDA_PIN)"? GpioPinSetLow
>>> resolves to the code above.
> Harald> That's a little bit unfair ;-). I do know almost nothing
> about Harald> STM32 and CM3. Anyway, I'll try, sorry if I missed
> Harald> Some chips seem to provide specific dedicated pin set/clear
> Harald> registers. Here we could use
> GPIOB-> BRR = (1 << I2CBUS1_SDA_PIN);
> Harald> I understood, that other STMs are different
> GPIOB-> BSRRL = I2CBUS1_SDA_PIN;
> No, all STM32 I know have Bit_set and Bit_clear register. STM32 ports
> are 16 bit wide. Both registers are stacked together as as 32 bit
> register, with set the lower 16 and reset the upper 16 bits. Some
> families also expose the reset register additional as the lower 16
> bit of a 4 byte aligned other 16-bit register
I was not aware, that there are chips that omit the BRR register to
reset the pins in the lower 16 bits.
And the BSRR (set and reset) register is designed with a good idea in
mind. This enables to change the pin states in both directions for
different pins at exactly the same point of time. There are reasons to
do this, like emulated data buses or switching an H-bridge.
> Harald> These statements take a single instruction only, same as bit
> Harald> banding. The advantage is, that it is faster than bit
> banding, Harald> because there is just a write cycle required.
> GpioPinSetLow Harald> needs an additional read cycle.
> 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?
AFAIK the bitband area is not an STM32 thing but an CortexM thing... not
sure, but I thought that this is available in any CortexM...
But I may be wrong.
> Harald> Again, correct me, if I'm wrong. I'm not familiar with this
> Harald> hardware, but you may get the idea.
> Harald> For other registers you may need bit banding. Then it is
> Harald> probably possible to create a less complicated macro and use
> it Harald> like
> Harald> BB_PERIPH(&GPIOB->ODR, I2CBUS1_SDA_PIN) = 1;
> Harald> which is easier to read than the swiss army knife version
> Harald> CM3BBREG(I2C_PORT, GPIO_Typedef, BSRR, Harald>
> 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).
> Harald> Several STM32 drivers extend the API with GPIO_PinAFConfig.
> Do Harald> you intend to integrate this into GpioPinConfigSet?
>>> The Pin needs configuration of the alternate mode. So again, how
>>> do you propose to write that code?
> 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.
I retreated from that 'must' and asked for a 'should'...
I already committed to the idea that switching to special functions of
chips and architectures is the job of the driver exported for that
So special port settings that disconnect the pin from its GPIO function
can be handled from a function 'disconnected' from the general gpio.h.
For STM32 and some other chips it doesn't make sense to write different
functions to just handle one or two cases more than the normal gpio
configuration function already does.
So what is possible to do without breaking the rules is
In gpio.h only pin set tokens are defined and the functions are wrapped
to the appropriate architecture functions.
in the architecture specific gpio.h the missing tokens are defined and
the same function is called.
This covers both cases with one function, without violating the rules
and as only defines are needed, it doesn't add additional code overhead.
> But if we ever see the alternate function setting in platform
> independant code, there is something wrong.
Right, so we have to think about how to handle gpio.h, arch/gpio.h and
the inclusion of the one by the other...
> So again, putting GPIO_PinAFConfig is internal platform
> implementation and other platforms and NUT/OS itself have very few
> reasons to care how it is done internal...
If there is no common way to declare a pin as non-gpio and there is no
architecture that benefits from that, then just skip it. I am not sure
if there may be an advantage from having a general _PINOFF or _ALTERNATE
options. And if it is only to enable debug code to detect if you use a
gpio that is assigned to a driver or a driver using special function
while the pin is still assigned as gpio...
I have no written code that uses or explains this scenario, just a
feeling that this might be an interesting option.
More information about the En-Nut-Discussion