【发布时间】:2016-09-20 02:28:15
【问题描述】:
通过 /dev/mem 写入硬件寄存器需要额外的写入
我想在 Linux 上使用 /dev/mem 写入一些硬件寄存器。 目标板是ZYBO(Zynq,ARM Cortex-A9),硬件是AXI4 Lite Slave,有4个寄存器,由Xilinx Vivado自动生成。
这是写入硬件寄存器的 C 代码。
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#define MAP_BASE (0x43c30000)
#define MAP_RANGE (0x10000)
int main(int argc, char *argv[])
{
volatile unsigned int *p;
void *iomap_ptr;
int fd, i, v;
fd = open("/dev/mem", O_RDWR | O_SYNC);
iomap_ptr = mmap(0, MAP_RANGE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MAP_BASE);
p = (volatile unsigned int *)iomap_ptr;
for (i = 0; i < 4; i++)
p[i] = i;
for (i = 0; i < 4; i++)
printf("%04X: %08X\n", i, p[i]);
munmap(iomap_ptr, MAP_RANGE);
close(fd);
return 0;
}
当我第一次运行 C 代码时,结果是:
0000: 00000000
0001: 00000001
0002: 00000002
0003: 00000000
好像最后的write没有应用。
然后,当我再次运行 C 代码时,结果是:
0000: 00000000
0001: 00000001
0002: 00000002
0003: 00000003
经过调查,我意识到我需要对硬件进行额外的写入才能应用最后一次写入。
如何在不进行额外写入的情况下写入硬件寄存器?
【问题讨论】:
-
是否需要刷新部分 D-Cache? Xilinx 应该有一些宏/函数用于使特定地址范围的缓存失效/刷新。
-
@rjp:地址空间不是“不可共享/非缓存/严格排序”(希望我没有遗漏什么),硬件设计被破坏了。外设寄存器空间不应出现缓存问题。
-
@Olaf,我不反对。我没有在 Vivado 方面工作过,所以我不知道这是否需要指定和/或是否可能设置不正确。
-
旁注:不要对外围寄存器使用标准整数类型,以及其他需要固定宽度类型的地方。使用
stdint.h类型。将完整的寄存器指针定义封装到宏中也是一种很好的做法。这样可以避免每次使用容易出错的指针时手动转换。 -
我从 Digilent 的基本系统设计中删除了视频 DMA、协议转换器和互连。最后,C 代码以某种方式正常工作。这很奇怪......我认为基本系统设计或我的设计充当了 FIFO。无论如何,谢谢大家的回复。
标签: arm embedded linux-device-driver embedded-linux memory-barriers