在我的项目中,数据从自定义IP写入BRAM(通过Block Ram IP生成器生成)。然后,我使用AXI BRAM控制器将内存与AXI总线接口,并使其可在ARM上运行的Linux上访问。
控制器的基地址为0x4200_0000,范围为8K(最大为0x4200_1FFF)。内存也有8K个位置,每个位置的宽度为32位。
为确保访问问题不在我的自定义IP中生成的数据中,我仅对每个8K地址(因此地址1包含0x01等,最多0x1fff)进行编号即可初始化内存。
尝试从Linux读取这些值时出现问题。在命令行上使用devmem 0x42000001
返回0x04000000和以下内容:
Alignment trap: devmem (1257) PC=0x0001ca94 Instr=0xe7902005 Address=0xb6f9d2fd FSR 0x011
这似乎表明Linux期望每个地址值映射到一个字节,而不是32位字。对齐陷阱一直发生,直到devmem 0x42000004
,它返回0x00000004,这是第四个方向的正确值,但是无法访问地址中不是4的倍数的值。 devmem 0x42000002
返回0x00040000(注意偏移0x04)以及对齐陷阱。我发现了使用mmap映射/ dev / mem的原始python脚本的问题:由于每个单独的地址似乎都映射到一个字节,因此我必须读取每个4个地址值,但这意味着我只能获取这四个值之一。
关于如何正确与AXI控制器及其背后的存储器接口的任何想法?
*******编辑以澄清我遇到的问题。如有疑问,请添加图片:
答案 0 :(得分:1)
这似乎表明Linux希望每个地址值都映射到一个字节
这是所有现代CPU中的标准映射。当您使用数据总线宽度超过8位的AXI时,最低地址位将从AXI数据总线中选择一个字节。请访问ARM网站并下载AXI规范。
控制器的基地址为0x4200_0000,范围为8K(最大为0x4200_1FFF)。内存也有8K个位置,每个位置的宽度为32位。
这是错误的,32位的8K具有8K * 4 = 0x0000 .. 0x7FFF的地址范围。
我建议您重新构建BRAM,但对Block Ram IP生成器使用不同的参数。
我更改了RAM,以便暴露给AXI控制器的端口以8位工作。 .....
您的Zynq AXI总线可能约为32位宽。因此,标准连接的内存应为32位宽,并应启用字节写功能。
如果将8位存储器连接到32位总线而没有这样做,或者错误地修改了地址,则可能会丢失4个字节中的3个。
我不清楚您确实想要哪种行为。
在情况2中,您应该使用不同的AXI地址:您应该将地址位上移两个位置,以便每个字节占用4个地址位置。 您还必须决定将字节放置在何处:
仅LS位置:将MS 24位绑定为零
仅MS位置:将LS 24位绑定为零
在所有4个位置重复:在32位上将字节复制四次。
您还喜欢什么。 (这是您的硬件,您可以执行所需的操作。)
请注意,对于连接到AXI总线的任何模块,应将前面的AXI分离器设置为覆盖正确的地址范围。但我认为您没有这些。