我正在尝试使用 busybox devmem 命令读取和写入寄存器。我从驱动程序的源代码中打印了它的基地址,并收到了以下地址: 0xffffff800bdd0000
我假设这是一个虚拟内核地址。我如何将其转换为物理地址,以便我可以使用 busybox devmem?我正在尝试从终端执行它,而不需要任何编程。
答案1
这标题您的问题得到答案:读取或写入/dev/kmem
设备节点。 (*1)
但是......阅读你的问题......我认为这并不是你正在寻找的。
我知道您想要读/写某个设备的某个特定寄存器。
无论哪种硬件设备(包括 RAM)通过特定总线与 cpu 通信,设备 I/O 寄存器的实际地址仅与设备使用的总线相关。
换句话说,访问这些地址......将需要遵循严格且特定的协议以及可能不同的读/写指令。
幸运的是,Linux 提供了一种抽象跨所有总线和设备执行 IO 的方法:内存映射 IO。和一个设备节点来访问统一的(ram 和 io)地址空间:/dev/内存(*2)
在做任何事情之前,你必须先确保该节点存在在您的系统上。出于明显的安全原因,许多发行版不启用它或限制其访问。因此,请检查内核 .config 文件是否设置了 CONFIG_DEVMEM 并且未设置 CONFIG_STRICT_DEVMEM。
如果不是这种情况,请使用您喜欢的工具相应地调整您的内核配置并重建您的内核。
那么您现在需要知道的是寄存器被重新映射到的地址:
与您在OP中断言的相反,您不应该知道它读取驱动程序源代码,因为该代码在逻辑上是以设备独立方式的基地址编写的。
从这段代码中你实际上可以理解的是你感兴趣的寄存器的相对地址。它的地址相对于基地址的偏移量。记下它(或从设备技术规格中获取)
Linux(如果成功)将与您的设备相关的 io 空间重新映射到的基地址应在/proc/iomem
文件中报告。 (*3)
将两者(基地址和偏移量)相加,即可得到寄存器重新映射的地址。
您现在需要使用 /dev/mem 设备节点,因为这一切都很简单……使用它确实是明智的busybox 设备内存。 (*4)
正如您所读到的那样使用它:devmem ADDRESS [WIDTH [VALUE]]
处理 WIDTH 参数(寄存器的大小(以位为单位))
1:或者可能曾有过自从有了答案莱纳斯·托瓦兹 (Linus Torvalds) 想要摆脱它。
2:在 x86_64 架构上,Linux 提供了另一种处理设备的方法(报告 /proc/ioports 中的端口地址并通过 /dev/port 访问),但由于这不适用于使用 arm 的 ARM 架构和 OP,因此无法访问设备寄存器由于重新映射 IO 是这里描述的唯一方法。
3:请注意,对于某些设备,内存重新映射范围可以分割在多个位置。阅读规范(或驱动程序代码)以了解寄存器引用的基址。
4:大胖警告:即使通过 devmem 等中介工具,使用不当也/dev/mem
可能会破坏您的系统。