在Petalinux 2020.2上移植xilinx_axidma库:一个ZYNQ开发者的避坑实录
在Petalinux 2020.2上移植xilinx_axidma库:一个ZYNQ开发者的避坑实录
当你在ZYNQ平台上尝试实现高速数据传输时,AXI DMA无疑是一个强大的工具。然而,将开源项目xilinx_axidma移植到Petalinux 2020.2环境的过程,却可能成为一场充满陷阱的冒险。本文将分享我在实际项目中踩过的坑,以及如何一步步解决这些问题的经验。
1. 环境准备与基础配置
在开始移植之前,确保你的开发环境已经正确搭建。我使用的是以下配置:
- Vivado 2020.2
- Petalinux 2020.2
- Ubuntu 18.04 LTS
关键检查点:
- 确认Vivado工程中已正确配置AXI DMA IP核
- 确保Petalinux项目基于正确的BSP创建
- 检查Ubuntu系统已安装所有必要的依赖包
提示:在开始前备份整个项目目录,因为后续的内核配置和设备树修改可能会需要多次尝试。
2. Linux内核配置的关键细节
内核配置是移植过程中最容易出错的部分之一。以下是必须确认的配置项:
CONFIG_CMA=y CONFIG_DMA_CMA=y CONFIG_XILINX_DMAENGINES=y CONFIG_XILINX_AXIDMA=y CONFIG_XILINX_AXIVDMA=y CONFIG_DMA_SHARED_BUFFER=y配置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.h>3.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_chrdev@0 { compatible = "xlnx,axidma-chrdev"; dmas = <&axi_dma_0 0 &axi_dma_1 0>; dma-names = "tx_channel", "rx_channel"; }; }; &axi_dma_0 { dma-channel@40400000 { xlnx,device-id = <0x1>; }; }; &axi_dma_1 { dma-channel@40410030 { 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在实际项目中,我遇到了多次设备树配置不生效的问题,最终发现是内核版本差异导致的解析方式变化。通过反编译生成的设备树二进制文件,才确认了问题所在。这也提醒我们,在嵌入式开发中,验证每个环节的实际效果至关重要,不能仅凭配置文件的修改就认为工作已经完成。
