我需要与基于 AXI-burst 接口的 FPGA 设备进行通信。在不涉及 DMA 的情况下,通过 Linux 访问此类设备的方法有哪些?Burst 是 AXI 标准的固有属性,通常应在传输大量数据时自动触发。更大的问题是 FPGA 被设计成只响应 AXI 总线上的突发类型请求。因此,当应用程序尝试顺序复制时,这会在 Linux 上引起严重问题。我已经尝试过memcpy
了,但它不起作用。
2 回答
我假设您的“FPGA 设备”是一个自定义块,通过 AXI 接口映射到 Cortex-A9 的内存。我认为有 2 或 3 种方法可以完成这项工作。
1) 可缓存映射。高速缓存硬件接口一次对整个高速缓存行进行突发传输。您需要手动清理(写入后)和无效(读取前)。
2) 不可缓存的映射,并有一个 ARM 汇编语言例程处理低级传输。我认为“加载和存储多个寄存器”指令可以提供您正在寻找的内容。
我遇到了类似的问题,需要通过 Cortex-A9 处理器的 8 字节传输访问 AXI 外设(自定义内存控制器)。当然,通常的 ARM 指令传输 1、2 或 4 个字节(字节、半字、字)。那些通过可缓存映射工作,但不是通过不可缓存映射。LDM/STM,一次 2 个单词,可用于两种映射。
当然,AHB/AXI 传输模式取决于实现。根据您的描述,您需要 INCR 或 WRAP 模式而不是 SINGLE。但它不应该是那样的。这带来了第三种方法可以使这项工作:
3) 与您的数字硬件设计师交谈,让他了解他的实施对软件的影响。
在我看来,你不应该做不寻常的/自定义的低级 MMU 操作。Linux 有高级方法,您可以在设备驱动程序和/或 board.c 中放置标准挂钩,主要选项是是否不缓存(即 COHERENT)。参考LDD3。
您需要设置 MMU 以通知硬件您的组件的功能。您还需要确保整个互连支持突发并且不进行任何转换(如果在生成互连时组件的功能存在任何歧义,则可能会发生这种情况)。
要设置 MMU,请执行如下调用:
/* shareable device: S=b0 TEX=b000 AP=b11, C=b0, B=b1 = 0xC06*/
Xil_SetTlbAttributes(COMPONENT_BASE_ADDRESS, 0xC06);
属性定义如下(来自Zynq 技术参考手册):
Encoding Bits Cache Attribute
C B
0 0 Non-cacheable
0 1 Write-back, write-allocate
1 0 Write-through, no write-allocate
1 1 Write-back, no write-allocate
所以上面的行会将区域设置为回写,写分配,这可能会给你写时的突发访问。
另请参阅Xilinx AR#47406和此论坛帖子。