Wednesday, September 9, 2015

Union Usage - Interpreting different value through the members

Union, like Structure can hold various members and each member can be of any data type.
But the basic difference is that at any given point, only one member of  Union can be accessed.
It means that the value/data of a member will be retained until data is stored in another member.
If the idea is to retain the value of individual member then obviously Structure needs to be used.
Union should be used keeping in mind that the same memory location will be used by all the members of Union.
Size of Union is same as the size of the largest member.
All the members in Union use the same memory location to store the respective values and this fundamental principle can be exploited in cases where the value stored in one member can be interpreted in another way though a different member.

Lets consider a hypothetical 32 bit register X. There are 4 fields of a byte each.

31 - 24
23 - 16
15 - 8
7 - 0
Control_1 bits
Status_1 bits
Control_0 bits
Status_0 bits

A Structure  representing the above diagram can be written as follows

struct regX {
        __u8 control_1;
        __u8 status_1;
        __u8 control_0;
        __u8 status_0;
}

Now we will write a Union which encapsulate the above structure along with the value of the register.

union regX_encaps {
        __u32 value;
        struct regX reg;
};

It should be noted that the "value" member is 32 bit and the "status / control" members are 8 bit each.
Since regX_encaps is a Union, the data present in the member .value can be accessed as struct regX.

        union regX_encaps registerX;
        registerX.value = 0xaabbccdd;
        printf("value of register is %x \n",registerX.value);
        printf("value of control_1 is %x\n",registerX.reg.control_1);
        printf("value of status_1 is %x\n",registerX.reg.status_1);
        printf("value of control_0 is %x\n",registerX.reg.control_0);
        printf("value of status_0 is %x\n",registerX.reg.status_0);
        return 0;

In the above example, data 0xaabbccdd is fed into reg of regX_encaps which can be accessed as individual byte.
Output of the above code
value of register is aabbccdd 
value of control_1 is bb
value of status_1 is aa
value of control_0 is dd
value of status_0 is cc

In a real time scenario, readl() will be used to feed the data into reg of regX_encaps. Perform the desired action on the individual byte (control_0, status_0 etc) and then write into that, effectively reg of regX has the entire data now and which can be written using writel()