[U-Boot] [PATCH v3 02/10] armv7: add miscellaneous utility macros

Simon Glass sjg at chromium.org
Tue Jun 14 17:11:50 CEST 2011


On Tue, Jun 14, 2011 at 6:53 AM, Wolfgang Denk <wd at denx.de> wrote:
> Dear Aneesh V,
>
> In message <4DF7488A.6000909 at ti.com> you wrote:
>>
>> Yes. I have seen those macros. But more often than not the bit field is
>> more than 1 bit wide and the value to be set is not necessarily all 0's
>> or all 1's. That's why I have to use clrsetbits_*()
>
> I see.  In such a case (and only then) clrsetbits_*() is indeed the
> right choice.
>
>> The problem I have to deal with is different. get_bit_field() was
>> intended to extract bit fields from an integer. So, the target usage
>> will be something like this(where a, b, and c are bit fields in
>> register my_reg)
>>
>> u32 my_reg, a_val, b_val, c_val;
>>
>> u32 my_reg = readl(my_reg_addr);
>>
>> a_val = get_bit_field(my_reg, a_mask);
>> b_val = get_bit_field(my_reg, b_mask);
>> c_val = get_bit_field(my_reg, c_mask);
>>
>> Do you see an alternative method for doing this using the standard
>> macros?
>
> Please see the example given here:
>
> http://article.gmane.org/gmane.comp.boot-loaders.u-boot/101146
>
> Looking closer, the "FIELD_VAL" macro alone will probably not suffice,
> as you need both shift directions, like that:
>
>        #define FIELD_SHIFT     16
>        #define FIELD_MASK      0xF
>
>
>        #define FIELD_BITS(x) (x << 16)
>        #define FIELD_MASK FIELD_BITS(0xF)
>        #define FIELD_VAL(x) ((x & FIELD_MASK) >> 16)

Hi Wolfgang,

I think you have FIELD_MASK being two meanings: the un-shifted or
'raw' mask, and the shifted mask. So perhaps:

        #define FIELD_SHIFT     16
        #define FIELD_RAWMASK      0xF

        #define FIELD_BITS(x) (x << 16)
        #define FIELD_MASK FIELD_BITS(FIELD_RAWMASK)
        #define FIELD_VAL(x) ((x & FIELD_MASK) >> 16)

or with the 16 factored properly, but even harder to read:

        #define FIELD_SHIFT     16
        #define FIELD_RAWMASK      0xF

        #define FIELD_BITS(x) (x << FIELD_SHIFT)
        #define FIELD_MASK FIELD_BITS(FIELD_RAWMASK)
        #define FIELD_VAL(x) ((x & FIELD_MASK) >> FIELD_SHIFT)

(note that FIELD_BITS should arguably mask after the shift).

When you have a lot of these definitions in a row you have mentally
check the bit width of the mask:

        #define FIELD1_RAWMASK      0xF
        #define FIELD1_SHIFT     16
        #define FIELD2_RAWMASK      0x1F
        #define FIELD2_SHIFT     11
        #define FIELD3_RAWMASK      0x1F
        #define FIELD3_SHIFT     7
        #define FIELD4_RAWMASK      0x1F
        #define FIELD4_SHIFT     1

        #define FIELD1_BITS(x) (x << FIELD1_SHIFT)
        #define FIELD1_MASK FIELD_BITS(FIELD1_RAWMASK)
        #define FIELD1_VAL(x) ((x & FIELD1_MASK) >> FIELD1_SHIFT)
        #define FIELD2_BITS(x) (x << FIELD2_SHIFT)
        #define FIELD2_MASK FIELD_BITS(FIELD2_RAWMASK)
        #define FIELD2_VAL(x) ((x & FIELD2_MASK) >> FIELD2_SHIFT)
...

Is the above correct, or do fields overlap or not cover fully?
(exercise for reader) (see [1] below)

So I think is better to think of the width rather than the mask.

        #define FIELD_SHIFT     16

        #define FIELD_RAWMASK (1U << FIELD_WIDTH)  - 1
        #define FIELD_BITS(x) (x << FIELD_WIDTH)
        #define FIELD_MASK FIELD_BITS(FIELD_RAWMASK)
        #define FIELD_VAL(x) ((x & FIELD_MASK) >> FIELD_WIDTH)

because then it is more obvious:

        #define FIELD1_WIDTH      4
        #define FIELD1_SHIFT     16
        #define FIELD2_WIDTH      5
        #define FIELD2_SHIFT     11
        #define FIELD3_WIDTH      5
        #define FIELD3_SHIFT      7
        #define FIELD4_WIDTH      5
        #define FIELD4_SHIFT      1

And now it is a little easier to see that 11+5 = 16, so FIELD2 is ok;
7+5=12 so FIELD3 overlaps, 1+5=6 so FIELD4 isn't big enough. It's
still not as good as just numbering your bits on little-endian archs,
but I think we have had that discussion.

I think BITS and VAL are not very descriptive which is why I suggested
pack and unpack at the time.

But don't get me started talking about bit fields.

Regards,
Simon

[1] This is why macros are so nice:

define once:
#define bf_mask(field)  ((field ## _RAWMASK) << field ## _SHIFT)
#define bf_val(field, val)  (((val) & bf_mask(field)) >> field ## _SHIFT)
#define bf_bits(field, val)  (((val) << field ## _SHIFT) & bf_mask(field))

then:
        #define FIELD1_BITS(x) bf_bits(FIELD1, x)
        #define FIELD1_MASK bf_mask(FIELD1)
        #define FIELD1_VAL(x) bf_val(FIELD1, x)
        #define FIELD2_BITS(x) bf_bits(FIELD2, x)
        #define FIELD2_MASK bf_mask(FIELD2)
        #define FIELD2_VAL(x) bf_val(FIELD2, x)
...


>
> The code would then look something like this:
>
>        my_reg = readl(my_reg_addr);
>
>        a_val = A_VAL(my_reg);
>        b_val = B_VAL(my_reg);
>        c_val = C_VAL(my_reg);
>
> ...or similar.
>
> Best regards,
>
> Wolfgang Denk
>
> --
> DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
> "I dislike companies that have a we-are-the-high-priests-of-hardware-
> so-you'll-like-what-we-give-you attitude. I like commodity markets in
> which iron-and-silicon hawkers know that they exist to  provide  fast
> toys for software types like me to play with..."    - Eric S. Raymond
>


More information about the U-Boot mailing list