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
- Next Article - C Programming #62: Typical Header file
- Previous Article - C Programming #60: Unions
- All Article - C Programming
No comments :
Post a Comment