Gay*_*lon 5 embedded dd devices mmap
看起来
root@testbox:~# dd if=/dev/mem bs=1 count=4 skip=2149646336 | hd
应该几乎等于
root@testbox:~# devmem 2149646336 32
但是,虽然devmem
效果很好,但该dd
调用给我带来了段错误。对于许多其他 bs,skip 组合(在我尝试解决这个问题时偶然发现的) dd 成功返回,但数据与我期望的完全不同。所有这些都表明,当我使用 dd 时,我实际上并没有解决我认为我正在解决的问题。也许是一些内存映射问题?我是一个硬件专家,所以我只考虑物理地址。
一些血淋淋的细节:
我正在构建一个嵌入式系统,其中 Linux 运行在带有片上 ARM A53 内核的 Xilinx FPGA 上。我经常使用 devmem 来读取或写入 FPGA 逻辑中的内存映射寄存器。我想使用 dd 而不是 devmem 通过一个命令读取一长串地址,并将数据保存到文件或通过管道将其传输到另一个进程。
我的 FPGA 设计有一个内部 RAM 块,可读写,映射到字节地址0x80210000
。
我写了一个shell脚本,如下所示:
devmem 0x80210000 32 0x5AB000CD
devmem 0x80210004 32 0x5AB001CD
devmem 0x80210008 32 0x5AB002CD
devmem 0x8021000C 32 0x5AB003CD
... etc etc <250 more lines> ...
devmem 0x802103F8 32 0x5AB0FECD
devmem 0x802103FC 32 0x5AB0FFCD
Run Code Online (Sandbox Code Playgroud)
它只是用一些可识别的乱码填充了我的块 RAM 的第一个 KB。执行该 shell 脚本后,我可以使用 devmem 从该内存中读取单词。
root@testbox:~# devmem 2149646336 32
0x5AB000CD
root@testbox:~# devmem 2149646340 32
0x5AB001CD
root@testbox:~# devmem 2149646344 32
0x5AB002CD
root@testbox:~# devmem 2149646348 32
0x5AB003CD
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。
请注意:
0x80210000 = 2149646336 十进制
和
0x80210000 / 16 = 134352896 十进制
接下来我尝试使用以下命令读取相同的 4 个单词的内存dd
:
root@testbox:~# dd if=/dev/mem of=/tmp/junk1 bs=1 count=16 skip=2149646336
或
root@testbox:~# dd if=/dev/mem of=/tmp/junk1 bs=16 count=1 skip=134352896
诸如此类。
这些行中的任何一行都会给我带来段错误。我尝试过许多其他的 bs、skip 等组合,试图找到我的内存块。
其他“成功”的调用dd
。例如:
root@testbox:~# dd if=/dev/mem bs=16 count=1 skip=2149646336 | hd
1+0 records in
1+0 records out
16 bytes copied, 0.00032236 s, 49.6 kB/s
00000000 ff ff fd ba 85 ff 4c ce ff ff bd df e4 d5 9d ed |......L.........|
00000010
Run Code Online (Sandbox Code Playgroud)
但我不认识这个数据。我想我只是从我的 DRAM 中的谁知道的地方读取。
dd if=/dev/mem
for 的寻址与 for的寻址不同吗devmem
?
部分答案:
如果您devmem
来自 busybox,它使用 /dev/mem来读取和写入值,因此您应该得到相同的结果。
也就是说,请注意,单位skip
是块(bs
字节),因此bs=16 count=1 skip=2149646336
不会在 0x80210000 处读取,而是在 0x802100000 处读取,这可能会包装到 0x02100000。
由于跳过的 MSB 是 1,因此如果源代码和/或编译器中的某处存在有符号/无符号混淆,也可能会搞砸。
所以我要做的第一件事是使用类似于bs=16 skip=134352896
. 如果仍然失败,我要做的第二件事是编写一个小型 C 程序,直接读取/dev/mem
并验证是否有效。