Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bit fields for reading from H/W registers

I want to read the 2nd, 5th and the 6th bit from a 32-bit register. I have decided to use struct bit fields to store them. Is the following data structure correct?

struct readData
{
    int unwanted:1;
    int reqbit1:1;
    int unwanted1:2;
    int reqbit2:2;
    int unwanted2:26;
};

I'm not sure about how the bit fields are created. I'm going to use an API that will copy bytes from the h/w register to this structure directly. In that case, will reqbit1 contain the 2nd bit? As per my understanding, the compiler allots the first bit to an int variable and the 2nd bit is alloted to another int variable and so the reqbit1 won't have any data read from the register. Isn't the following union more suitable for this situation?

union readData
{
    struct readBits
    {
        bool unwanted:1;
        bool reqbit1:1;
        xxx unwanted1:2;
        short reqbit2:2;
        xxx unwanted2:26;
    };

    int regValue;
};

If this is right, what should I declare unwanted2 as?

like image 442
linuxfreak Avatar asked Feb 15 '23 23:02

linuxfreak


2 Answers

Usually it is used the following union:

union readData {
   struct {
      unsigned int unwanted:1;
      unsigned int reqbit1:1;
      unsigned int unwanted1:2;
      unsigned int reqbit2:2;
      unsigned int unwanted2:26;
   } readBits;
   unsigned int regValue;
};

EDIT :

The usage is:

 #define REG_ADDRESS 0x12345678 // e.g.

 union readData* rd = (union readData*)REG_ADDRESS;

 char bit2 = rd->readBits.reqbit1;
 char bits56 = rd->readBits.reqbit2;
like image 72
Alex Avatar answered Feb 26 '23 22:02

Alex


From the C standard: "The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined."

So you shouldn't use bitfields where the order matters.

Use explicit masking and shifting instead:

reqbit1 = (w >> 1) & 1;    
reqbit2 = (w >> 4) & 3;

or

reqbit1 = (w & 0x00000002) >> 1;    
reqbit2 = (w & 0x00000010) >> 4;

and for the other direction

w = (reqbit1 << 1) | (reqbit2 << 4);

The "unwanted" parts are typically named reserved1 and so on.

like image 31
starblue Avatar answered Feb 26 '23 23:02

starblue