引言
在涉及Xilinx Zynq UltraScale+ MPSoC的项目中,实现设备间高速、低延迟的数据传输往往是核心需求之一。PCIe(尤其PS侧)结合DMA(直接内存访问)正是满足这类需求的理想技术方案。
在近期支持的客户项目中,其核心需求在于:在一款PCB单板上,集成两颗Zynq MPSoC器件,并利用其PS侧的PCIe控制器,直接构建点对点DMA数据传输链路,从而避免引入额外的PCIe交换芯片。为了验证该方案的可行性并积累经验,我们使用两块ZCU102开发板成功搭建并测试了一个工作Demo。
这篇文章将聚焦这一实战过程,手把手带你完成:环境搭建、硬件配置、驱动移植、系统编译到最终的上板测试验证,目标是帮你快速在你的MPSoC项目上实现类似的高速DMA互连!
一、实战准备:软硬件环境搭建
1.1硬件准备
开发板:两块Xilinx ZCU102开发板。
连接线:一根PCIe公对公延长线缆。
角色分配
板卡1:配置为RC(Root Complex)。
板卡2:配置为EP(Endpoint)。
物理连接:将两块板的PS侧PCIe插槽通过延长线缆直接相连(如下图所示)。
1.2 软件准备
软件版本
Vivado:2021.2(用于硬件设计和比特流生成)。
PetaLinux:2021.2(用于嵌入式Linux系统构建)。
1.3 驱动准备
(Xilinx PCIe Root and EndPoint - Xilinx Wiki - Confluence[1])我们需对其进行交叉编译以生成适用于ARM64架构的内核模块(.ko)。
注:
二、详细实现过程拆解
2.1 硬件设计(RC端配置-Vivado)
① 创建block design后,添加“Zynq Ultrascale+ MPSoC” IP。
② 运行Block automation,进行基础配置。
③ 注意将自动生成的“maxihpm0_fpd_aclk”和“maxihpm1_fpd_aclk”与“pl_clk0”连线,否则会导致后面validate不通过。
④ Vivado通常已自动分配管脚,默认模式为RC,使用GT Lane 0。在“IO Configuration”的页面可以看到,PCIE默认配置为Gen2 x1,其他GT Lane分别配置给DP/USB3.0/SATA。本实验使用默认配置。
⑤ PCIE高级配置,勾选“Switch To Advanced Mode”。
确保Class Code值设置为0x060400(代表PCI-to-PCI Bridge)。如果使用错误的类代码,Linux在枚举时可能导致BAR分配失败!其余高级配置一般可用默认值。
⑥ 配置完成后,按照“Generate Output Products” ->“Create HDL Wrapper”->“Generate Bitstream”的流程。成功生成比特流后,导出.xsa文件,用于PetaLinux系统构建。
2.2 构建Linux系统(RC端-Petalinux)
① petalinux工程创建
petalinux-create --type project -s xilinx-zcu102-v2021.2-final.bsp -n zcu102_rc
② 导入硬件描述(.xsa)
petalinux-config -- get-hw-description = (path of zcu102_rc.xsa)
③ 配置Linux内核
petalinux-config -c kernel
由于内核配置中默认开启了ps PCIe的DMA,为了避免后面安装外部驱动时冲突,这里需要去掉Xilinx PS PCIe DMA support的默认勾选。
④ 编译工程
petalinux-build
⑤ 打包文件
petalinux-package --boot --fsbl zynqMP_fsbl --u-boot u-boot.elf --force
生成BOOT.BIN、image.ub、boot.scr等关键启动文件。将上述生成的启动文件复制到SD卡的boot分区。
2.3 编译移植PS PCIE DMA驱动(RC端)
① 获取并修改驱动源码:从Xilinx Wiki获取驱动源码。由于官方提供的驱动源码是在X86 host上编译执行的,还需要将其修改为可在ARM上执行的ko文件,即交叉编译。
② 修改Makefile,将KERNEL_DIR指定为本地内核代码所在路径。内核路径示例(请根据实际路径修改):
/home/your_user_name/petalinux_pro/peta_2021/zcu102_rc/build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.10+gitAUTOINC+568989d441-r0/linux-zynqmp_generic-standard-build。
③ 在驱动源码目录执行make命令,成功编译后会生成ps_PCIe_dma.ko内核模块文件。
④ 将编译生成的ko文件、apps路径下的simple_test应用文件以及petalinux打包好的Boot.bin、image.ub和boot.scr都拷贝至SD。
2.4 硬件准备(EP端)
① vivado配置(类似RC,但关键点不同)
a.在IO configuration中明确将PCIe模式设置为Endpoint。
b.关键修改,将Device ID修改为“0XA808”。此值必须与驱动源码中ZYNQMP_DMA_DEVID1定义的预期设备ID严格匹配,否则驱动无法正常运行。
② 生成并导出硬件设计。
③ 创建EP端Boot文件,在vitis中:基于导出的.xsa文件新建Vitis平台工程。创建一个简单的Hello World应用程序工程(仅用于加载运行基本固件)。将其复制到EP板SD卡。
2.5上板实测
① 上电启动:
将准备好的SD卡(含boot文件)分别插入两块ZCU102。
两块板均设置为SD卡启动模式。
连接RC板的串口到主机终端(如PuTTY或minicom)。
② EP枚举观察(RC串口输出):
给两块板上电。
在RC板的串口终端中,你应该能看到类似XXX:PCI host bridge /PCIe@fd0e0000 ranges:和XXX:PCIe:Link up的日志信息,这表明PCIe链路已成功建立并枚举到EP设备。
③ 加载驱动(RC端命令):
在RC板的Linux命令行中,进入存放驱动的目录。
执行:insmod ps_pcie_dma.ko
检查设备节点:成功加载后,/dev/PCIe(例如/dev/ps_pcie_epdma0)等设备节点应被创建。
④ 运行DMA测试程序(RC端命令):
执行命令进行传输测试(以下仅为示例命令,具体参数需看程序说明):./simple_test
⑤ 测试结果解读:
程序运行后,终端会打印传输的速度数据。
在我们的测试中(Gen2 x1链路):
RC -> EP(写入EP内存):传输4MB数据,平均速度约为372MB/s。
EP -> RC(写入RC内存):传输4MB数据,平均速度约为378MB/s。
本文详细展示了如何利用两块Xilinx Zynq UltraScale+ MPSoC ZCU102开发板,通过配置其PS侧PCIe控制器分别作为RC和EP,最终实现了两者之间基于DMA驱动的高速数据互传功能。该方案验证了在MPSoC设计中直接利用片上PCIe资源构建高速点对点链路的可行性。
三、资源分享
① GitHub - Xilinx/zynqmp-psPCIe-epdma
② Zynq UltraScale+ Device Technical Reference Manual(UG1085)•查看器•AMD技术信息门户网站
文章来源:安富利