Bitfield Allocation

The Compiler provides six predefined bitfield allocation macros (as shown in the following listing):

Listing: Predefined Bitfield Allocation 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 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).

Listing: Using Predefined Bitfield Allocation Macros
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.

Listing: __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 is non-portable and inefficient due to the masking involved in unpacking individual fields. We recommend that you use regular bit-and (&) and bit-or (|) operations for I/O port access.