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?
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);
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.
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.
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)
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.)
WriteReg((int *) 0x80000000, 4, res);
printf("Reg2 = %i\n", res);
You write res to register, not read it. So res is still uninitialized.
User contributions licensed under CC BY-SA 3.0