In C, a pointer to a structure that needs to access a list of byte pointers
First off, sorry for the title, it was hard to come up with a description. I am attempting to create a structure that will access a peripheral that has quite of few internal registers that are controlled by 3 address lines. So I have the following structure definition:
typedef struct {
union {
unsigned char *reg0aPtr;
unsigned char *reg0bPtr;
} RegsAddrOffset0;
union {
unsigned char *reg1aPtr;
unsigned char *reg1bPtr;
} RegsAddrOffset1;
...
union {
unsigned char *reg7aPtr;
unsigned char *reg7bPtr;
} RegsAddrOffset7;
} DeviceRegMap;
Then if I declare a variable as so
DeviceRegMap *uartRegMap = (DeviceRegMap *)(0xD0000000);
Now, if I try to to use the uartRegMap variable to access the memory mapped registers I thought I would see tha开发者_运维技巧t *(uartRegMap->RegsAddrOffset0.reg0aPtr) would read the data from address 0xD0000000, which is does. If I use *(uartRegMap->RegsAddrOffset1.reg1bPtr) I thought I would access 0xD0000001, but it is actually accesses address 0xD0000004. Since the processor is 32-bit the natural alignment is 4-bytes. I am thinking since the size of a pointer is an int which in this case is 32-bits this is the reason why I am accessing on 4-byte address ranges (e.g., 0xD0000000, 0xD0000004, 0xD0000008, etc).
If I declared an instance of the DeviceRegMap datatype I would expect the following initialization:
DeviceRegMap uartRegMap = {
(unsigned char *)0xD0000000,
(unsigned char *)0xD0000001,
...
(unsigned char *)0xD0000007,
};
Then if I wanted to access address 0xD0000007 then I would use *(uartRegMap.RegsAddrOffset7.reg7bPtr)
The question is why is the pointer to the DeviceRegMap data type access memory on 4-byte alignments (e.g., 0xD0000000, 0xD0000004, etc) instead of byte alignments (e.g., 0xD0000000, 0xD0000001, etc). With regards to the toolset I am using Wind River diab compiler. Thanks.
Mark
EDIT: Based upon abelenky's comment
If you want to access the byte-sized parts of a memory-mapped register, do the following:
struct DeviceRegMap {
volatile unsigned char byte0;
volatile unsigned char byte1;
volatile unsigned char byte2;
volatile unsigned char byte3;
};
static struct DeviceRegMap *device = (struct DeviceRegMap *)(0xD0000000);
Now device->byte0
points to 0xD0000000
, and device->byte3
points to 0xD00000003
. Is that what you want?
Most compilers have a way to indicate that a structure should be packed tightly, without padding for alignment purposes.
I'm not familiar with your compiler, but explore the documentation for something like
#pragma pack
before your structure definition.
精彩评论