在Petalinux 2020.2上移植xilinx_axidma库:一个ZYNQ开发者的避坑实录
在Petalinux 2020.2上移植xilinx_axidma库一个ZYNQ开发者的避坑实录当你在ZYNQ平台上尝试实现高速数据传输时AXI DMA无疑是一个强大的工具。然而将开源项目xilinx_axidma移植到Petalinux 2020.2环境的过程却可能成为一场充满陷阱的冒险。本文将分享我在实际项目中踩过的坑以及如何一步步解决这些问题的经验。1. 环境准备与基础配置在开始移植之前确保你的开发环境已经正确搭建。我使用的是以下配置Vivado 2020.2Petalinux 2020.2Ubuntu 18.04 LTS关键检查点确认Vivado工程中已正确配置AXI DMA IP核确保Petalinux项目基于正确的BSP创建检查Ubuntu系统已安装所有必要的依赖包提示在开始前备份整个项目目录因为后续的内核配置和设备树修改可能会需要多次尝试。2. Linux内核配置的关键细节内核配置是移植过程中最容易出错的部分之一。以下是必须确认的配置项CONFIG_CMAy CONFIG_DMA_CMAy CONFIG_XILINX_DMAENGINESy CONFIG_XILINX_AXIDMAy CONFIG_XILINX_AXIVDMAy CONFIG_DMA_SHARED_BUFFERy配置CMA内存区域进入内核配置菜单petalinux-config -c kernel导航到Library routines→CMA配置设置CMA大小为25MB根据实际需求调整注意如果Vivado工程中已包含AXI DMA IP核大部分相关配置可能已经自动启用但仍需手动验证。3. 源码修改与适配开源xilinx_axidma库需要针对Petalinux 2020.2进行多处修改。以下是关键修改点3.1 头文件包含修改在axi_dma.c中新增头文件包含#include linux/of_dma.h3.2 设备配置函数修改修改axidma_chrdev.c中的设备配置调用// 原代码 // of_dma_configure(dev-device, NULL, true); // 修改后 of_dma_configure(dev-pdev-dev, NULL, true);3.3 用户空间访问验证更新axidma_chrdev.c中的访问验证函数static bool axidma_access_ok(const void __user *arg, size_t size, bool readonly) { if (!readonly !access_ok(VERIFY_WRITE, arg, size)) { axidma_err(Argument address %p, size %zu cannot be written to.\n, arg, size); return false; } else if (!access_ok(VERIFY_READ, arg, size)) { axidma_err(Argument address %p, size %zu cannot be read from.\n, arg, size); return false; } return true; }3.4 DMA回调函数适配修改axidma_dma.c中的回调函数static void axidma_dma_callback(void *data) { struct axidma_cb_data *cb_data; struct kernel_siginfo sig_info; cb_data data; if (cb_data-comp ! NULL) { complete(cb_data-comp); } else if (VALID_NOTIFY_SIGNAL(cb_data-notify_signal)) { memset(sig_info, 0, sizeof(sig_info)); sig_info.si_signo cb_data-notify_signal; sig_info.si_code SI_QUEUE; sig_info.si_int cb_data-channel_id; send_sig_info(cb_data-notify_signal, sig_info, cb_data-process); } }4. 设备树配置的陷阱与解决方案设备树配置是另一个容易出错的关键环节。以下是需要特别注意的部分4.1 设备树结构理解Petalinux项目中的设备树文件结构plnx_workspace/device-tree/device-tree/ ├── system-top.dts # 顶层设备树 ├── pl.dtsi # PL部分设备树 └── system-user.dtsi # 用户自定义修改4.2 关键设备树修改在system-user.dtsi中添加以下内容/include/ system-conf.dtsi / { }; amba_pl { axidma_chrdev: axidma_chrdev0 { compatible xlnx,axidma-chrdev; dmas axi_dma_0 0 axi_dma_1 0; dma-names tx_channel, rx_channel; }; }; axi_dma_0 { dma-channel40400000 { xlnx,device-id 0x1; }; }; axi_dma_1 { dma-channel40410030 { xlnx,device-id 0x2; }; };4.3 设备树验证技巧使用以下命令反编译设备树验证修改是否生效dtc -I dtb -O dts -o system.dts system.dtb注意在Xilinx Linux 5.4内核中设备树配置需要特别注意channel ID的分配这与4.x内核有所不同。5. 驱动与应用模块的创建与集成5.1 创建驱动模块petalinux-create -t modules --name xilinx-axidma --enable修改Makefile关键内容DRIVER_NAME xilinx-axidma $(DRIVER_NAME)-objs axi_dma.o axidma_chrdev.o axidma_dma.o axidma_of.o obj-m : $(DRIVER_NAME).o MY_CFLAGS -g -DDEBUG ccflags-y ${MY_CFLAGS}5.2 创建测试应用petalinux-create -t apps --name xilinx-axidma-test --enable测试应用的Makefile示例APP xilinx-axidma-test APP_OBJS axidma_transfer.o util.o libaxidma.o all: build build: $(APP) $(APP): $(APP_OBJS) $(CC) -o $ $(APP_OBJS) $(LDFLAGS) $(LDLIBS)6. 验证与性能测试完成所有修改后按照以下步骤验证驱动加载内核模块insmod /lib/modules/5.4.0-xilinx-v2020.2/extra/xilinx-axidma.ko运行测试程序axidmabenchmark -t 0 -r 1 -b 16000 -s 16000成功运行的输出示例AXI DMA Benchmark Parameters: Transmit Buffer Size: 0.02 MiB Receive Buffer Size: 0.02 MiB Number of DMA Transfers: 1000 transfers Using transmit channel 0 and receive channel 1. Single transfer test successfully completed! Beginning performance analysis of the DMA engine. DMA Timing Statistics: Elapsed Time: 0.14 s Transmit Throughput: 106.15 MiB/s Receive Throughput: 106.15 MiB/s Total Throughput: 212.31 MiB/s在实际项目中我遇到了多次设备树配置不生效的问题最终发现是内核版本差异导致的解析方式变化。通过反编译生成的设备树二进制文件才确认了问题所在。这也提醒我们在嵌入式开发中验证每个环节的实际效果至关重要不能仅凭配置文件的修改就认为工作已经完成。