Hi,
MadDog posted on Apr 27 2006 at 07:46 PM said:
struct UART
{
...
struct
{
char value :8;
u8 reserved :8;
}rhb; //Receive buffer register (holding register & fifo register)
...
}
Looks like a good idea, and I think the kernel source does it in a similar, but not quite so elegant way.
You may be running into structure alignment and packing issues. I had some major problems with this until I discovered a few things:
By default, a structure is padded at the end to make the structure size a multiple of the machine's preferred alignment size (in this case, 1 word, or 4 bytes). I also found that individual items within a structure can have padding inserted so that each element is word-aligned. Needless to say, this was great fun with a structure which defined a 24-bit RGB triplet...
If you put " __attribute__ ((packed))" at the end of your structure definition, it will eliminate the padding that occurs between structure elements.
If you use "#pragma pack(push,n)" (where 'n' is your preferred alignment in bytes) before your structure definitions, and "#pragma pack(pop)" afterwards, then the structure alignment and padding at the very end will be adjusted to 'n' bytes, which by default is 4.
So, in your example above, I think your 2-byte 'rhb' structure is being turned into an 8-byte structure, because there is a 3-byte padding between 'value' and 'reserved', and also a 3-byte padding at the end.
To fix this, I would try the following:
#pragma pack(push,1)
struct UART {
struct {
char value :8;
u8 reserved :8;
} __attribute__ ((packed)) rhb; //Receive buffer register (holding register & fifo register)
] __attribute__ ((packed));
#pragma pack(pop)
The padding at the very end is probably not much of an issue in your case, but it does become important if you have a multiple-structure array addressed by a pointer, where the actual sizes of the structures are not multiples of 4-bytes.
Note that structures within structures will also need to have the packed attribute defined if it's needed, as they don't seem to inherit their parent's attribute.
NB. I'm not sure how this affects bitfields, as I never use them, but I think it might be worth examining. I guess the best way to check would be if you declare a pointer to your structure, and see what happens to the pointer address when you do an increment (i.e. ptr++), as that will show you exactly how the structure is aligned and what size it is. I usually use "objdump -x -d -S" to generate a listing of the binary, so that I can have a look at the assembler source and see how the pointer arithmetic is working out.