tags:

views:

95

answers:

6

Hi all,

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 wanna 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?

Thanks a lot, Martin

+2  A: 

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.

Jonathan
+2  A: 

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.

Michael Burr
+3  A: 

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);
AraK
Thanks for your answer, I updated the function accordingly as you suggested (see above). However, the problem still remains, I am not able to read back the correct value, the error remains more or less the same. Anyone an idea what could still be wrong with my pointers?
Martin
A: 

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)
Ziffusion
A: 

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.)

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

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

Vovanium