The Compiler provides six predefined bitfield allocation macros (as shown in the following listing):
__BITFIELD_MSBIT_FIRST__ /* defined if bitfield allocation starts with MSBit */ __BITFIELD_LSBIT_FIRST__ /* defined if bitfield allocation starts with LSBit */ __BITFIELD_MSBYTE_FIRST__ /* allocation of bytes starts with MSByte */ __BITFIELD_LSBYTE_FIRST__ /* allocation of bytes starts with LSByte */ __BITFIELD_MSWORD_FIRST__ /* defined if bitfield allocation starts with MSWord */ __BITFIELD_LSWORD_FIRST__ /* defined if bitfield allocation starts with LSWord */
Using the defines listed above, you can write compatible code over different Compiler vendors even if the bitfield allocation differs. Note that the allocation order of bitfields is important (as shown in the following listing).
struct { /* Memory layout of I/O port: MSB LSB name: BITA | CCR | DIR | DATA | DDR2 size: 1 1 1 4 1 */ #ifdef __BITFIELD_MSBIT_FIRST__ unsigned int BITA:1; unsigned int CCR :1; unsigned int DIR :1; unsigned int DATA:4; unsigned int DDR2:1; #elif defined(__BITFIELD_LSBIT_FIRST__) unsigned int DDR2:1; unsigned int DATA:4; unsigned int DIR :1; unsigned int CCR :1; unsigned int BITA:1; #else #error "undefined bitfield allocation strategy!" #endif } MyIOport;
If the basic bitfield allocation unit in the Compiler is a byte, the bitfield memory allocation is always from the most significant BYTE to the least significant BYTE (big endian). For example, __BITFIELD_MSBYTE_FIRST__ is defined as shown in the following listing.
struct { unsigned char a:8; unsigned char b:3; unsigned char c:5; } MyIOport2; /* LSBIT_FIRST */ /* MSBIT_FIRST */ /* MSByte LSByte */ /* MSByte LSByte */ /* aaaaaaaa cccccbbb */ /* aaaaaaaa bbbccccc */