Bit fields for reading from H / W registers

I want to read the 2nd, 5th and 6th bits from a 32-bit register. I decided to use structural 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 am not sure how bit fields are created. I am going to use an API that will directly copy bytes from the h / w register into this structure. In this case, reqbit1 will contain the second bit? As far as I understand, the compiler allocates the first bit of the int variable, and the second bit - the other variable int, so reqbit1 will not have data read from the register. Is the next alliance no longer 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 correct, what should I declare as undesirable2 how?

+3
source share
3 answers

From C standard: "The order of the distribution of bit fields within a device (from high order to low or low order) is determined by the implementation."

Thus, you should not use bit fields where order matters.

Use explicit masking and switching instead:

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

or

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

and for another direction

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

Unwanted parts are usually called reserved1 , etc.

+2
source

The following union is usually used:

 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:

Using:

  #define REG_ADDRESS 0x12345678 // eg union readData* rd = (union readData*)REG_ADDRESS; char bit2 = rd->readBits.reqbit1; char bits56 = rd->readBits.reqbit2; 
+2
source

Why not use sizeof() and check the number of bytes assigned to each member of the structure? Elements of the structure can be found here.

Why copy the h / w register to a structure and then work with the bits of the structure? It may be the case that the h / w register is updated with a new value, but the structure is still not updated.

If you want to read the 2nd, 5th and 6th bits, you can achieve this as follows:

 #define myregister ((unsigned long*)address of register) unsigned long ret=0; ret = myregister & (1<<2); if(ret) { ... } ret = myregister & (1<<5); if(ret) { ... } //... and so on 

IMHO, a kiss (keep it Simple, stupid).

+1
source

Source: https://habr.com/ru/post/955628/


All Articles