Адреса отображения памяти с использованием простого определения препроцессора - PullRequest
2 голосов
/ 20 октября 2010

У меня простой интерфейс с отображением памяти, и я хотел бы написать через это значения для двух регистров, а затем прочитать их обратно. Следующий код пример отлично работает:

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

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

Вместо "жесткого кодирования" адресов, я хотел бы, чтобы адрес был собрать из базового адреса и смещения. Используя какой-то препроцессор заявления, я хочу иметь некоторые определения.

НАЧАЛО ОБНОВЛЕНИЯ

 #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);    

КОНЕЦ ОБНОВЛЕНИЯ

Вывод теперь в любом случае 1073804536 вместо 12 и 23 соответственно. Итак, я полагаю, что я сделал что-то ужасное с указателями, кто угодно комментарий, как я могу правильно построить этот адрес с помощью оператора define?

Ответы [ 6 ]

3 голосов
/ 20 октября 2010

Видите ли, вы добавляете смещение в байтах.Вы должны либо изменить свой код на:

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

Или вы можете добавить смещение в терминах вашего типа:

  WriteReg(base, 0, 12);
  WriteReg(base, 1, 23);
2 голосов
/ 20 октября 2010

Проблема в том, что, поскольку base - это int*, когда макрос расширяется до чего-то вроде (макрос ReadReg, используемый в примере):

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

Вы добавляете 4на указатель на int, арифметика которого приводит к увеличению на (4 * sizeof(int)) байт.

2 голосов
/ 20 октября 2010

Поскольку тип указателя int, вам следует добавить к нему 1 вместо 4, если вы хотите перейти к следующему int по порядку.Помните, вы сейчас делаете арифметику с указателями.

0 голосов
/ 23 октября 2010
  WriteReg((int *) 0x80000000, 4, res);
  printf("Reg2 = %i\n", res);

Вы пишете res для регистрации, а не читаете его. Так что res все еще неинициализирован.

0 голосов
/ 21 октября 2010

Эта программа, как написано в настоящее время, использует WriteReg четыре раза и ReadReg ноль раз.Возможно, вторые два раза вы намеревались вызвать ReadReg вместо WriteReg.res неинициализирован, поэтому неудивительно, что он печатается как бессмысленное значение дважды.(Это также не объявлено, но я предполагаю, что вы только что это упустили.)

0 голосов
/ 20 октября 2010

Я бы изменил ваши макросы следующим образом:

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

#define ReadReg(BaseAddress, RegOffset, Data) \
    Data = *(unsigned*)((unsigned)BaseAddress + (unsigned)RegOffset)
...