开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜