我很难弄清楚如何解决以下问题。我在一个内存非常少的嵌入式系统上,希望最大限度地减少内存使用量。 指针总是让我感到困惑,并且总会这样做。
我有一大堆寄存器地址定义:
#define GPIO_PORTA_BASE (*((volatile unsigned long *)0x40004000))
#define GPIO_PORTB_BASE (*((volatile unsigned long *)0x40005000))
//etc..
这些寄存器可直接访问。 e.g:
GPIO_PORT_BASE &= 0x01;
我需要的是一个包含上述寄存器的数组,以便我可以轻松地将它们映射到索引。 e.g:
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的代码。
任何见解都将受到赞赏。
答案 0 :(得分:9)
我不知道为什么@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;
答案 1 :(得分:3)
通常的方式是声明一个结构,例如:
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;
}
答案 2 :(得分:0)
如果我找对你,这应该足够了:
volatile unsigned long* GPIO_PORTA = (volatile unsigned long*) 0x40004000;
您可以将其用作
volatile unsigned long regxx = GPIO_PORTA[0x17];
// even
GPIO_PORTA[10] &= 0xF000;
答案 3 :(得分:0)
我认为你要做的是这样的事情:
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