c - 了解嵌入式 C 中的 I/O 内存位置
问题描述
• 声明一个指针,
int *p;
• 将 I/O 内存位置的地址分配给指针
p = (int*) 0x30610000;
我想访问0x30610000
具有我要配置的寄存器的内存位置。为什么要键入强制类型转换呢?不应该p =0x30610000;
指向位置吗?
解决方案
int *p;
p = (int*) 0x30610000;
方法和实现都不好。
- 使用宏(不是指针变量)来访问映射到地址空间的硬件寄存器。这是更有效的方式。
- 使用固定大小的整数。
- 将寄存器声明为
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
. 这是因为编译器需要更多的指令来检索寄存器的地址。
推荐阅读
- swift - SwiftUI 是否可以调用该函数并从其他页面更改视图?
- python-3.x - 无法使用函数对列名重新排序
- php - 如何将自定义参数/属性从树枝模板传递到自定义表单字段?
- javascript - 如何从开发者控制台访问“exerciseObject”?
- python - 我正在尝试解密我的填充但只收到 1 个字符
- javascript - React:useEffect 中的昂贵计算阻塞了渲染
- sql - 时间序列数据的孤岛和缺口问题
- java - 2020-12-21T13:00:00.000+0000 的 SimpleDateFormat 掩码
- logging - 如何在 Kubernetes 集群上使用 EFK 架构访问 LoadBalancer 日志文件
- php - 我正在尝试向我的 PHP 脚本添加分页,但它不起作用并且总是显示 HTTP 错误 500