Bitfield Allocation

The Compiler provides six predefined macros to distinguish between the different allocations:

Listing: Predefined Macros


  
__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 above-listed defines, you can write compatible code over different Compiler vendors even if the bitfield allocation differs. Note that the allocation order of bitfields is important (refer to the following listing).

Listing: Compatible bitfield allocation
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 allocation unit for bitfields in the Compiler is a byte, the allocation of memory for bitfields is always from the most significant BYTE to the least significant BYTE. For example, __BITFIELD_MSBYTE_FIRST__ is defined as shown in the following listing:

Listing: __BITFIELD_MSBYTE_FIRST__ definition
/* example for __BITFIELD_MSBYTE_FIRST__ */
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 */
Note: There is no standard way to allocate bitfields. Allocation may vary from compiler to compiler even for the same target. Using bitfields for I/O register access to is non-portable and, for the masking involved in unpacking individual fields, inefficient. It is recommended to use regular bit-and (&) and bit-or (|) operations for I/O port access.