Jun 6, 2016

C Programming #61: Union and bit-field example - register

C Programming #61: Union and bit-field example - register

This article will explain best example of Unions and bit-fields in representing registers. Registers are storage location which is accessible to CPU or when writing device drivers (device which might be on some bus like I2C, SPI, PCIe) will have registers which is used for Configuration(Read/Write) or Status(Read) of the register. Generally registers will have different fields in it. Unions along with Bit-fields


Say there fictitious 8 bit registers which is as follows

Bits Field
7 Status
6-5 Reserved
4-0 Address

Above 8 bit register can be represented in using bit-fields as follows

typedef struct reg_t {
   unsigned char status:1;
   unsigned char reserved:2;
   unsigned char address:5;
}reg_tag;

We could now use above bit-fields with long with union as follows

typedef union r_t {
  unsigned char val;
  reg_tag s;
}r_tag;

Using above concept we could write the following C program for demo

#include <stdio.h>

typedef struct reg_tag {
   unsigned char status:1;
   unsigned char reserved:2;
   unsigned char address:5;
}reg_t;

typedef union r_tag {
  unsigned char val;
  reg_t s;
}r_t;

int main() 
{
   r_t r;

   r.val = 0;
   r.s.status = 1;
   r.s.address = 0x4;

   printf("r.val is %d, r.s.status is %d, r.s.address is %d\n",
          r.val, r.s.status, r.s.address);

   return 0;
}
r.val is 33, r.s.status is 1, r.s.address is 4

Above union need to redefined depending on endianness

typedef struct reg_tag {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   unsigned char status:1;
   unsigned char reserved:2;
   unsigned char address:5;
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
   unsigned char address:5;
   unsigned char reserved:2;
   unsigned char status:1;
#else
#error "Unknown endianess"
#endif
}reg_t;

Links

No comments :

Post a Comment