了解嵌入式 C 中的 I/O 内存位置

Understanding I/O memory location in embedded C

• 声明一个指针,

int *p;

• 将 I/O 内存位置的地址分配给 指针

 p = (int*) 0x30610000;

我想访问内存位置 0x30610000,其中有一个我想配置的寄存器。 我们为什么要强制转换它? p =0x30610000; 不应该指向位置吗?

int *p;

p = (int*) 0x30610000;

方法和实现都不好

  1. 使用宏(不是指针变量)访问映射到地址 space 的硬件寄存器。这是更有效的方法。
  2. 使用固定大小的整数。
  3. 声明寄存器为volatile。它们肯定很容易产生副作用 :)
#define  REG1  (*(volatile uint32_t *)0x30610000)

和用法:

REG1 = 0x456;
foo(REG1);

大多数外设都有一个以上的寄存器。最好使用结构来访问它们(注意 volatile 关键字所在的位置。不要使整个结构 volatile):

typedef struct
{
    volatile uint32_t DR;
    volatile uint32_t CR;
    volatile uint32_t SR;
}UART_type;

#define UART1 ((UART_type *)0x45678000)

和用法:

UART1 -> CR = 0x45676;

在 C 语言中,需要强制转换才能使警告静音,因为它是一个 UB(或者可能只是定义为 @Clifford 建议的实现)。即使实现(如 ARM-gcc)以可预测的方式进行 - 它仍会发出警告。

现在,为什么指针对象的效率低于 #define。这是因为编译器需要更多的指令来检索寄存器的地址。