简体   繁体   English

将指针写入GPIO输出引脚的地址

[英]Writing pointers to the address of GPIO out pin

Absolute noob to embedded system. 嵌入式系统的绝对菜鸟。 Right now I am trying to program a device called nRF52832 in C . 现在,我正在尝试在C编程一个名为nRF52832的设备。 I know that the base address for the GPIO is 0x50000000 and the offset for the OUT register is 0x504 . 我知道GPIO的基址是0x50000000 ,而OUT寄存器的偏移量是0x504 How do I create pointers to the addresses of the GPIO OUT and print the address? 如何创建指向GPIO OUT地址的指针并打印地址?

Do I do 我会做吗

volatile unsigned int* GPIO_BASE = (unsigned int*) 0x50000000;
volatile unsigned int* GPIO_OUT = GPIO_BASE + 0x504; ?

Remember that pointer arithmetic is always done in the units of the pointer base type. 请记住,指针算术始终以指针基本类型为单位进行。

That means the expression GPIO_BASE + 0x504 will add a byte-offset of 0x504 * sizeof *GPIO_BASE , which is 0x504 * sizeof(int) (which on most systems will be an offset of 5136 bytes, not 1284 bytes). 这意味着表达式GPIO_BASE + 0x504将添加0x504 * sizeof *GPIO_BASE的字节偏移量,即0x504 * sizeof(int) (在大多数系统上,其偏移量为5136字节,而不是1284字节)。

If you want to add an offset of 0x504 bytes you need to divide it by the size of the pointer base type: 如果要添加0x504 字节的偏移量, 0x504需要将其除以指针基本类型的大小:

volatile unsigned int* GPIO_OUT = GPIO_BASE + (0x504 / sizeof *GPIO_BASE);

Except this problem your code is correct, and a very common way to access hardware registers. 除此问题外,您的代码是正确的,并且是访问硬件寄存器的非常常用的方法。

Do I do 我会做吗

 volatile unsigned int* GPIO_BASE = (unsigned int*) 0x50000000; volatile unsigned int* GPIO_OUT = GPIO_BASE + 0x504; 

No, you don't. 不,你没有。 That would mean that the address gets calculated in run-time, because the volatile qualifier means that the program has to update the variable in run-time whenever it is used. 这将意味着在运行时计算地址,因为volatile限定符意味着程序必须在运行时随时更新变量。

This is what you should do instead: 这是您应该做的:

// assuming 32 bit registers and 0x504 being the offset in bytes
#define GPIO_BASE 0x50000000u
#define GPIO_OUT  (*(volatile uint32_t*)(GPIO_BASE + 0x504u))
#define GPIO_X    (*(volatile uint32_t*)(GPIO_BASE + 0x508u)) // some other related register 

...
GPIO_OUT = something;

In this example, the register addresses are calculated at compile-time, which is the only correct way of doing it. 在此示例中,寄存器地址是在编译时计算的,这是唯一的正确方法。

By de-referencing the address inside the macro, we can now use GPIO_OUT almost as if it was an ordinary variable. 通过取消引用宏中的地址,我们现在可以像使用普通变量一样使用GPIO_OUT了。

It does however seem unlikely that a GPIO peripheral has hundreds of memory-mapped registers, so the value 0x504 is strange. 但是,GPIO外设似乎不太可能具有数百个内存映射寄存器,因此值0x504很奇怪。


Also please note that using the default C types like int and char in embedded systems is naive. 还请注意,在嵌入式系统中使用默认的C类型(例如intchar是幼稚的。 These types come with various portability problems and also have various forms of poorly-defined behavior associated with them. 这些类型具有各种可移植性问题,并且还具有与它们相关的各种形式的定义不明确的行为。 Professional systems only use the types from stdint.h and never anything else. 专业系统仅使用stdint.h的类型,而不会使用其他任何类型。

volatile unsigned int* GPIO_BASE = (unsigned int*) 0x50000000;
volatile unsigned int* GPIO_OUT = GPIO_BASE + 0x504; 

If offset for the OUT register is 0x504 bytes away from BASE , then you need to typecast GPIO_BASE to char * 如果OUT寄存器的offsetBASE相距0x504字节,则需要将GPIO_BASE类型转换为char *

volatile unsigned int* GPIO_OUT = ((char *)GPIO_BASE) + 0x504; 

Otherwise all ok. 否则一切正常。

Because of pointer arithmetic, the value of the pointer GPIO_OUT will be GPIO_BASE + (0x504 * sizeof(int)). 由于采用了指针算法,因此指针GPIO_OUT的值为GPIO_BASE +(0x504 * sizeof(int))。 If sizeof(int) is 4 bytes, you will get pointer to 0x50000000 + (0x504 * 4) = 0x50001410, while the actual address for the OUT register is 0x50000504. 如果sizeof(int)是4个字节,则将获得指向0x50000000 +(0x504 * 4)= 0x50001410的指针,而OUT寄存器的实际地址为0x50000504。 You can type-cast the pointer to unsigned char* or better yet use macro. 您可以将指针类型转换为无符号char *或更好地使用宏。

#define GPIO_BASE 0x50000000 #定义GPIO_BASE 0x50000000

#define GPIO_OUT GPIO_BASE + 0x504 #定义GPIO_OUT GPIO_BASE + 0x504

volatile unsigned int* gpio_out = GPIO_OUT; volatile unsigned int * gpio_out = GPIO_OUT;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM