Memory mapping addresses using simple preprocessor define

2

I have a simple memory mapped interface, and I would like to write through this values to two registers and then read them back. The following code example works fine:

  volatile int *reg1 = (int *) 0x80000000;
  volatile int *reg2 = (int *) 0x80000004;

 *reg1 = 12; *reg2 = 23;  
 printf("reg1 = %i\n", *reg1);
 printf("reg2 = %i\n", *reg2);

Instead of "hardcoding" the addresses, I would like the address to be put together from a base address and an offset. Using some preprocessor statements, I want to have some defines.

BEGIN UPDATE

 #define WriteReg(BaseAddress, RegOffset, Data) \
  *((volatile int *)((char*)BaseAddress + RegOffset)) = (unsigned int)(Data)

 #define ReadReg(BaseAddress, RegOffset, Data) \
  (unsigned int)(Data) = *((volatile int *)((char*)BaseAddress + RegOffset))  


  WriteReg((int *) 0x80000000, 0, 18);
  WriteReg((int *) 0x80000000, 4, 29); 

  WriteReg((int *) 0x80000000, 4, res);
  printf("Reg2 = %i\n", res);

  WriteReg((int *) 0x80000000, 0, res);
  printf("Reg1 = %i\n", res);    

END UPDATE

The output is now in either case 1073804536, instead of 12 and 23, respectively. So I assume I must have done something horrible wrong with the pointers, anyone a comment how I can properly build up this address with a define statement?

c
c-preprocessor
asked on Stack Overflow Oct 20, 2010 by Martin • edited Mar 1, 2016 by Brian Tompsett - 汤莱恩

6 Answers

3

You see, you are adding the offset as bytes. You either have to change your code to:

*((volatile int *)((char*)BaseAddress + RegOffset)) = (unsigned int)(Data)

Or, you can add the offset in-terms of your type:

  WriteReg(base, 0, 12);
  WriteReg(base, 1, 23);
answered on Stack Overflow Oct 20, 2010 by AraK
2

As the pointer type is int, you should be adding 1 to it instead of 4 if you want to move to the next int in sequence. Remember, you are doing pointer arithmetic now.

answered on Stack Overflow Oct 20, 2010 by Jonathan
2

The problem is that since base is an int* when the macro expands to something like (the ReadReg macro being used in the example):

// ReadReg(base, 4, res)
res = *(base + 4)

You're adding 4 to an int pointer, which pointer arithmetic causes to increment by (4 * sizeof(int)) bytes.

answered on Stack Overflow Oct 20, 2010 by Michael Burr
0

I would change your macros as follows:

#define WriteReg(BaseAddress, RegOffset, Data) \
    *(unsigned*)((unsigned)BaseAddress + (unsigned)RegOffset) = (unsigned int)(Data)    

#define ReadReg(BaseAddress, RegOffset, Data) \
    Data = *(unsigned*)((unsigned)BaseAddress + (unsigned)RegOffset)
answered on Stack Overflow Oct 20, 2010 by Ziffusion
0

This program as currently written uses WriteReg four times and ReadReg zero times. Perhaps the second two times you intentded to invoke ReadReg instead of WriteReg. res is uninitialized, so it's not surprising that it prints as a nonsensical value twice. (It's also not declared, but I assume you just left that out.)

answered on Stack Overflow Oct 21, 2010 by Larry Engholm
0
  WriteReg((int *) 0x80000000, 4, res);
  printf("Reg2 = %i\n", res);

You write res to register, not read it. So res is still uninitialized.

answered on Stack Overflow Oct 23, 2010 by Vovanium

User contributions licensed under CC BY-SA 3.0