固定有关C/C 的知识差距并注册访问



诚然,我是C 的新手。不幸的是,我看到的大多数代码要么使用asm调用或定义extern函数,其主体在汇编文件中。

这就是为什么我非常退出以找到以下代码的原因。我已经研究了代码库3天了。

句法我了解下面代码的每一行;除了重要的是因为我不明白它的工作方式!

  1. types.h定义u32uintptr(我已经看过它们)
  2. 当C和C 代码混合时,需要IFDEF __cplusplus。特别是因为extern C是C 特异的。如果GCC具有-fno-exceptions参数
  3. ,则可以省略
  4. volatile用于防止编译器进行任何优化,因为该地址必须是完美的,因为它是写入/从寄存器中/读取的。

所有的话,我仍然不知道该代码实际上是如何写或从寄存器中读取的。

#include <circle/types.h>
#ifdef __cplusplus
extern "C" {
#endif
static inline u32 read32 (uintptr nAddress)
{
    return *(u32 volatile *) nAddress;
}
static inline void write32 (uintptr nAddress, u32 nValue)
{
    *(u32 volatile *) nAddress = nValue;
}
#ifdef __cplusplus
}
#endif
#endif

*(unsigned int *)是什么意思?这是如何用于读写寄存器的?nAddress是否必须是物理地址

您正在寻找"内存映射输入输出"。

CPU与外部硬件交谈的最常见方法是通过内存总线 - 用于访问正常内存的相同总线。

首先,请记住,CPU与内存的互动不仅涉及读取和写入,还涉及诸如总线错误处理(无效访问),仲裁(多个访问相同内存的设备)和路由之类的东西(CPU可能希望访问多个多个内存设备)。为了处理此问题,使用A BUS协议

要写或读取外部存储器CPU必须启动A 交易。它的确切顺序是由使用的总线协议定义的,但通常涉及以下步骤:

  • 发送转移地址,类型,长度等。
  • 接收响应 - 允许或拒绝(总线错误)。
  • 如果允许交易传输实际数据。

启动转移的设备称为 master 启动器,而负责处理交易的设备称为 slave 目标

确定从属处理事务的设备称为解码器路由器。因此,交易通常会从主转到解码器,然后再到从设备。

总线协议当然提供了一种将数据传输到设备或从设备传输的方法。该设备可以是存储设备或其他任何设备。对于存储设备,其控制器通过编写或从内存单元格数字编写或读取数据来处理转换。

如果您熟悉面向对象的编程,则可以通过接口来考虑CPU连接到外部设备, 允许在指定地址读取和写作。该接口的实现可以做任何事情。这是完成内存映射I/O的方式 - CPU连接到一堆设备,每个设备都在特定地址范围内接收交易。将数据写入一个地址,将通过存储设备接收该数据,该数据将其存储到内存单元格数组,将数据写入另一个地址,可以通过SD Controller接收,并将其解释为" send send_status命令到SD卡"。

如果您也熟悉现代操作系统,则可以想到"一切都是文件"抽象。有些文件只是普通文件,例如他们充当记忆。其他文件不同。就像在Linux上阅读/proc/cpuinfo一样,您可以为您提供有关CPU的信息一样,在某些地址上阅读可以为您提供有关IRQ当前正在待处理的信息或告诉您邮箱目前有多少消息的信息。

公交协议的示例是AXI和AHB。AHB更简单,AXI更复杂,更快。在覆盆子Pi的情况下,很可能是将CPU连接到硬件的AXI协议。


因此,关于您的问题,这两个功能用于通过内存映射的I/O访问外部设备的寄存器。您正确正确的一切:

  • volatile用于防止编译器删除,重新排序或以任何方式更改这些内存访问 - 没有此硬件将无法执行我们想要的操作。
  • u32之所

(unsigned int *)是一种铸造到unsigned int指针的类型。取消运算符*用于访问该指针指向的内存位置。

最新更新