指针数组(*(volatile unsigned long *)0x40004000)

时间:2021-11-17 12:33:31

I am having a very hard time figuring out how to solve the following problem. I am on an embedded system with very little memory and want to minimize memory usage. Pointers have always confused the heck out of me and will always do.

我很难搞清楚如何解决以下问题。我在一个内存非常少的嵌入式系统上,希望尽量减少内存使用量。指针总是让我感到困惑,并且总是这样。

I have a whole bunch of defines for register addresses:

我有一大堆寄存器地址定义:

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

These registers are direct accessible. e.g:

这些寄存器可直接访问。例如:

GPIO_PORT_BASE &= 0x01;

What I need is an array that contains the above registers so that I can easily map them to an index. e.g:

我需要的是一个包含上述寄存器的数组,以便我可以轻松地将它们映射到索引。例如:

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

What I need to end up being able to do is something like this:

我最终需要做的是这样的事情:

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

I am using gcc to compile my code for arm cortex m3.

我正在使用gcc来编译arm cortex m3的代码。

Any insight would be appreciated.

任何见解将不胜感激。

4 个解决方案

#1


9  

I don't know why @Etienne deleted his answer, but it contained the essential information: The address is cast to volatile unsigned long *. That's what you need an array of.

我不知道为什么@Etienne删除了他的答案,但它包含了基本信息:地址被转换为volatile unsigned long *。这就是你需要的数组。

typedef volatile unsigned long* reg_addr;

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

We need to take the address again (&GPIO_PORTA_BASE), since the macro automatically dereferences them. Access as:

我们需要再次获取地址(&GPIO_PORTA_BASE),因为宏会自动取消引用它们。访问:

*registers[i] &= your_value;

#2


3  

Usual way is to declare a struct, for example :

通常的方法是声明一个结构,例如:

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

then to access it :

然后访问它:

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

EDIT: I just realized that I haven't answered the question. So, here it is :

编辑:我刚才意识到我没有回答这个问题。所以,这里是:

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

#3


0  

If I'm getting you right, this should be enough:

如果我找对你,这应该足够了:

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

You could use that as

你可以用它作为

volatile unsigned long regxx = GPIO_PORTA[0x17];

// even

GPIO_PORTA[10] &= 0xF000;

#4


0  

What I think you're trying to do is something like this:

我认为你要做的是这样的事情:

volatile unsigned long * gpio_porta = &GPIO_PORTA_BASE;

If you're using C++, you could also do the following:

如果您使用的是C ++,还可以执行以下操作:

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

And use it as:

并将其用作:

reg_foo &= 0x1;

However, most times I would expect a base address register to actually be stored as a pointer, rather than as the dereference of the pointer. Because of that, I would probably want your macros to be defined as:

但是,大多数情况下,我希望基址寄存器实际上存储为指针,而不是指针的取消引用。因此,我可能希望将您的宏定义为:

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

And then you could simply access them as

然后你可以简单地访问它们

GPIO_PORTA_BASE[3] &= 0x1

#1


9  

I don't know why @Etienne deleted his answer, but it contained the essential information: The address is cast to volatile unsigned long *. That's what you need an array of.

我不知道为什么@Etienne删除了他的答案,但它包含了基本信息:地址被转换为volatile unsigned long *。这就是你需要的数组。

typedef volatile unsigned long* reg_addr;

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

We need to take the address again (&GPIO_PORTA_BASE), since the macro automatically dereferences them. Access as:

我们需要再次获取地址(&GPIO_PORTA_BASE),因为宏会自动取消引用它们。访问:

*registers[i] &= your_value;

#2


3  

Usual way is to declare a struct, for example :

通常的方法是声明一个结构,例如:

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

then to access it :

然后访问它:

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

EDIT: I just realized that I haven't answered the question. So, here it is :

编辑:我刚才意识到我没有回答这个问题。所以,这里是:

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

#3


0  

If I'm getting you right, this should be enough:

如果我找对你,这应该足够了:

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

You could use that as

你可以用它作为

volatile unsigned long regxx = GPIO_PORTA[0x17];

// even

GPIO_PORTA[10] &= 0xF000;

#4


0  

What I think you're trying to do is something like this:

我认为你要做的是这样的事情:

volatile unsigned long * gpio_porta = &GPIO_PORTA_BASE;

If you're using C++, you could also do the following:

如果您使用的是C ++,还可以执行以下操作:

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

And use it as:

并将其用作:

reg_foo &= 0x1;

However, most times I would expect a base address register to actually be stored as a pointer, rather than as the dereference of the pointer. Because of that, I would probably want your macros to be defined as:

但是,大多数情况下,我希望基址寄存器实际上存储为指针,而不是指针的取消引用。因此,我可能希望将您的宏定义为:

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

And then you could simply access them as

然后你可以简单地访问它们

GPIO_PORTA_BASE[3] &= 0x1