[En-Nut-Discussion] Do we need something like sbv/sbi to complement sbi/cbi?

Ulrich Prinz ulrich.prinz at googlemail.com
Sat Dec 31 17:14:22 CET 2011


Hi!

Am 29.12.2011 17:11, schrieb Uwe Bonnes:
> Hello,
> 
> in Ulrich's devnut_m3n, some function used
>   sbi( ) and cbi()
> 
> Obvious, the stm libraries define register bits with their bit value
> #define  TIM_SR_UIF                          ((uint16_t)0x0001)
> and not bit positions like
> #define  TIM_SR_UIF_BIT                         0
> 
There is a discrepancy in the usage of these defines. I prefer the
bitmask instead of the bitnumber while a good compiler should translate
both things to the correct value without adding extra code.
But sometimes I prefer the bit number again....

If you need to setup a device and you have 10 lines of _BV() | _BV() |
_BV... it is unreadable code...
But if you need to set a bit fast / atomic it is best to use the bitband
area but the macros need the bit number for address calculation.
The impact is pretty high if you switch an SPI-Select by old style
gpio |= _BV(cs) or via bitband.

So you cannot define a stric rule of how to declare register bits. For
configuration masks are comfortable, for toggling and fast switching
numbers are needed.

---
Btw:

The first development run targets the functionality and the porting of
the c files from stm32f10x_xxx.c in stm-lib format to more faster and
compact code for nutos in stm32_xxx.c

It will be a second run to convert and optimize stm32f10x.h and its
relatives for the devices like stm32f10x_dev.h
The latter should be elliminated completely and only the stm32f10x.h
should be left.

-----
For register word / bit access and setting / toggling masks and bits:

Please look at the stm32_gpio.c and it's relevant .h file.
All gpio functions are single cycle single access regardless of their names.

Using the bitband functions as a reference any Cortex Register can be
access atomic for switching single bits in it.

> The s/cbi macro expands in devnut_m3n expands like
> #define cbi(_reg, _bit)         outr(_reg, inr(_reg) & ~_BV(_bit)) 
> and was used like
>   cbi( &TIM->SR, TIM_SR_UIF );
> and so things got wrong.

You can check the bitband access from gpio and transfer it to any
register of the Cortex. It is importand that the bitband macros expect
the bit-number not the bit mask.
> 
> The coding style rules say  that direct register access like 
> TIM2->SR |=  TIM_SR_UIF 
> is deprecated. So either explicit writing
> outr(_reg, inr(_reg) & _mask)
> is needed, or some macros to do so. In my tree I added
> 
For Cortex it doesn't make any difference and it is the preferred method
to use register pointers as ARM architecture in general does not need
any inr or outr things.

> #define sbv(_reg, _mask)         outr(_reg, inr(_reg) | _mask)
> #define cbv(_reg, _mask)         outr(_reg, inr(_reg) & ~_mask)
> #define bv_is_set(_reg, _mask)  ((inr(_reg) & _mask)) != 0)
> 
For compatibility or coding style ( even I hate this typing overhead
making code unreadable) you can substitude inr( reg) by (reg) and outr(
reg, v) by (reg) = (v)

See Haralds comment for the needed braces around the parameters. They
are very important :)

Best regards
Ulrich



More information about the En-Nut-Discussion mailing list