Массив указателей типа (* (volatile unsigned long *) 0x40004000) - PullRequest
9 голосов
/ 21 ноября 2011

Мне очень трудно понять, как решить следующую проблему. Я использую встроенную систему с очень небольшим объемом памяти и хочу минимизировать использование памяти. Указатели всегда выводили меня из себя и всегда будут делать.

У меня есть целая куча определений для адресов регистров:

#define GPIO_PORTA_BASE      (*((volatile unsigned long *)0x40004000))
#define GPIO_PORTB_BASE      (*((volatile unsigned long *)0x40005000))
//etc..

Эти регистры имеют прямой доступ. например:

GPIO_PORT_BASE &= 0x01;

Мне нужен массив, содержащий вышеупомянутые регистры, чтобы я мог легко сопоставить их с индексом. например:

not_sure_what_to_declare_the array_as port_base_array[] {
   GPIO_PORTA_BASE,
   GPIO_PORTB_BASE,
   //etc
}

Что мне нужно для того, чтобы я смог это сделать, это что-то вроде этого:

volatile unsigned long *reg;
*reg_a = port_base_array[0];
reg_a &=0x1;

Я использую gcc для компиляции кода для arm cortex m3.

Любое понимание будет оценено.

Ответы [ 4 ]

9 голосов
/ 21 ноября 2011

Я не знаю, почему @Etienne удалил свой ответ, но он содержал важную информацию: адрес приведен к volatile unsigned long *. Это то, что вам нужно массив.

typedef volatile unsigned long* reg_addr;

reg_addr registers[] = {
  &GPIO_PORTA_BASE,
  &GPIO_PORTB_BASE,
  // ...
};

Нам нужно снова взять адрес (&GPIO_PORTA_BASE), так как макрос автоматически разыменовывает их. Доступ как:

*registers[i] &= your_value;
3 голосов
/ 21 ноября 2011

Обычным способом является объявление структуры, например:

struct RegsAtAddrA
{
  unsigned int array1[10];
  char val1;
  // etc
};

, а затем доступ к ней:

volatile RegsAtAddrA *pRegsA = (volatile RegsAtAddrA *) 0x40004000;
pRegsA->val1= 'a';
//etc

РЕДАКТИРОВАТЬ: я только что понял, что я не ответил на вопрос,Итак, вот оно:

#include <iostream>
unsigned long a=1;
unsigned long b=2;
volatile unsigned long *port_base_array[] = {
   &a,
   &b,
   //etc
};
int main()
{
    std::cout<<"a="<<*port_base_array[0]<<std::endl;
    std::cout<<"b="<<*port_base_array[1]<<std::endl;
}
0 голосов
/ 21 ноября 2011

Я думаю, что вы пытаетесь сделать что-то вроде этого:

volatile unsigned long * gpio_porta = &GPIO_PORTA_BASE;

Если вы используете C ++, вы также можете сделать следующее:

volatile unsigned long & reg_foo = (&GPIO_PORTA_BASE)[3];
volatile unsigned long & reg_foo = gpio_porta[3];

Ииспользуйте его как:

reg_foo &= 0x1;

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

#define GPIO_PORTA_BASE      ((volatile unsigned long *) 0x40004000)
#define GPIO_PORTB_BASE      ((volatile unsigned long *) 0x40005000)

И тогда вы могли бы просто получить к ним доступ как

GPIO_PORTA_BASE[3] &= 0x1
0 голосов
/ 21 ноября 2011

Если я вас правильно понял, этого должно быть достаточно:

volatile unsigned long* GPIO_PORTA = (volatile unsigned long*) 0x40004000;

Вы можете использовать это как

volatile unsigned long regxx = GPIO_PORTA[0x17];

// even

GPIO_PORTA[10] &= 0xF000;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...