This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

What determines bit order in structure definition

Other Parts Discussed in Thread: CONTROLSUITE

I had a question about the bit order in bit data structure for F28069 platform.

F28069 is little endian MCU, I thought the bit order starts from the bottom of the structure, such as

struct tXclkBitsStruct

{

Uint16 Rsvd1  :9;   //bit[15:7]. reserved

Uint16 XCLKINSEL  :1;    //bit[6], XCLKIN Source Select

Uint16 Rsvd2  :4;    //bit[5:2]. Reserved

Uint16 XCLKOUTDIV  :2;   //bit[1:0]. XCLKOUT Divide Ration

};

However, TI's example shows the opposite, i.e, bit 0 starts on the top, as shown below

struct XCLK_BIT

{

Uint16 XCLKOUTDIV  :2;    //bit[1:0]. XCLKOUT Divide Ratio

Uint16 rsvd1  :4;    //bit[5:2]. reserved

Uint16 XCLKINSEL   :1;   //bit[6], XCLKOUT source select

Uint16 rsvd2   :9;    //bit[15:7], reserved

};

I want to define the bit structure for my data variables and union the bit structure with a Uint16 word.

So what determines the bit order from bottom or top? Is it documented in C compiler manual or somewhere else?

Please advise.

Thanks a lot!

  • Hello Louis!

    Regarding bytes:

    big endian - an addressing protocol in which bytes are numbered from left to right within a word. More
    significant bytes in a word have lower numbered addresses. 

    little endian - an addressing protocol in which bytes are numbered from right to left within a word. More
    significant bytes in a word have higher numbered addresses.

    Regarding bits:

    big-endian -  compiler allocates bit fields of MSBit to LSBit  in bytes of the variable container.

    little-endian - compiler allocates bit fields of LSBit to MSBit  in bytes of the variable container.

    Thus your second structure is a "little-endian" variant. if you pay attention on the F2806x device support library from controlSUITE then you will find indirect evidence for this conclusion.

    Regards,

    Igor

  • I was under the impression that bit field order and allocation are not part of the ANSI standard. The compiler can order the bits LSB or MSB first regardless of endianess. But convention would use the underlying processor endianess for defining the order. The compiler may not even use single bits. It could just use use "int" for each field. The compiler may not even pack them together. All that said, a lot of code would break if compilers did anything they wanted.

    For the C28x, the compiler doc spru514f does not state which order it uses. The assembler doc spru513f does say the fields are declared LSB first.

    Using masks would be better. You still have to handle endianess but at a byte level. The network stacks have macros for that. Linux has macros for that as well.

    Try posting in the Development Tools - Compiler forum. Those guys are pretty thorough about the ANSI standard and they do respond to posts.

  • Norman Wong said:

    The assembler doc spru513f does say the fields are declared LSB first.

    Yes, indeed this is very "sacramental" quote (p.246):

    C2000 is a little-endian machine, but it does not make sense to talk about the endianness of the bits in an indivisible unit such as char. By convention, we consider the data in a char to be stored least-significant octet first, then most-significant octet.

    About ANSI in fact this is really funny http://ndevilla.free.fr/endian/ ;-)

    Regards,

    Igor

  • It's understood that LSB is stored at lower address in little-endian unit, or transferred first in little-endian serial communicatio format.

    My question was for bit structure definition, should bit 0 be from top or bottom in a structure definition for little-endian unit? Since the bit structure is written in C, I would think it's a matter of C compiler. I was unable to find the rules other than testing.

    Thank your reply.

     

  • Hi Louis!

    I think the best way when you will create own structures is to use examples from device support library of controlSUITE (for example please look at F2806x_Gpio.h -  there are all structures like your second one (XCLK_BIT) from first post).

    Regards,

    Igor

  • Louis,

    The compiler always orders structures from top to bottom. The endianness of the CPU addressing is what actually makes it little-endian. For example, if you have this structure:

    struct DEMO
    {
        Uint16 v1;
        Uint16 v2;
        Uint16 v3;
        Uint16 v4;
    }

    then v1 always goes at offset 0x0, v2 goes at offset 0x1, v3 goes at offset 0x2, and v4 goes at offset 0x3. In a little-endian CPU, v1 and v3 are in the lower 16 bits of a 32-bit word. In a big-endian CPU, v2, and v4 are in the lower 16 bits. But the addresses don't change. The only reason to change the structure order in your code is to get the same layout in memory for mixed 16-bit and 32-bit accesses on different machines.

    For bitfields, there isn't a well-defined standard. ANSI C defines the syntax for bitfields, but everything else is implementation-dependent. In TI compilers, bitfields are stored in the same "endianness" as bytes. For little-endian, the first bitfield structure element goes in the LSB, the second goes in the next-lowest bit(s), and so on. However, in register diagrams, bits are always numbered with the LSB as bit 0, even on big-endian devices (e.g. TMS470).

    If you're using an F2806x, then everything is little-endian. The first structure element (bitfield or Uint16) goes in the least-significant bits of the memory word. This gets a brief mention in section 7.1.7 of the C28x compiler user's guide (SPRU514E).

    Please let me know if you have any further questions.