摘要:本文介绍了飞腾D2000处理器在国产嵌入式实时操作系统Reworks下实现PCIe XDMA驱动适配的完整方案。重点讲解了XDMA驱动的核心功能实现,包括H2C/C2H数据通道、MSI中断处理、BAR空间配置等关键技术点。文章提供了详细的驱动架构设计、飞腾平台BSP适配流程、字符设备操作实现,以及可直接编译运行的用户态测试代码。针对国产化环境中常见的MSI中断不触发、数据异常等问题给出了解决方案。该方案已在实际项目中验证,适用于FPGA加速、高速数据采集等场景,为国产处理器平台下的PCIe设备驱动开发提供了可复用的参考实例。

引言:国产化嵌入式开发必看!飞腾D2000 + Reworks 平台 XDMA PCIe 驱动适配,全程实战无废话,代码可直接复制编译,解决MSI中断、H2C/C2H数据搬移、BAR配置等核心痛点,新手也能快速上手,收藏备用,避免踩坑!

标签:飞腾D2000、XDMA、Reworks、PCIe驱动、国产化适配、MSI中断、FPGA、H2C、C2H、驱动移植、ARM64

  • 飞腾D2000 + Reworks | XDMA PCIe驱动适配 | 实战教程+完整代码

目录

一、XDMA 适配准备

1. 设计原理

2. 硬件信息

二、XDMA 功能与调用流程

1. C2H 读操作(FPGA → 主机)

2. H2C 写操作(主机 → FPGA)

3. Events 中断事件(MSI)

三、驱动文件结构

四、Reworks + 飞腾D2000 BSP 适配流程

1. 环境确认

2. BSP 配置要点

3. PCI 设备匹配配置

XDMA+FPGA配置如下:

3.1  XDMA简介

3.2  Pcie 基础设置

3.3  Pcie 总线标准硬件协议设置

3.4  Pcie BAR 内存映射设置

3.5 Pcie 总线中断功能配置

3.6 pcie 自带dma配置

3.7 引脚接口介绍

3.8  设计概述

3.9  数据交互流程

3.10 XDMA中断模式

3.11 图像输出扩展

3.12 核心模块设计(xdma_inter.v)

3.13 XDMA IP核心特性说明

3.14 中断模式说明

3.15 工程补充说明

3.16  衔接前文:Reworks系统下XDMA BSP适配延伸

4. BAR 数量与大小定义

5. MSI 中断适配(Reworks/GIC)

6. XDMA 驱动初始化

五、字符设备 fops 实现

1. SGDMA(H2C/C2H)操作集

2. 偏移控制(FIOSEEK)

3. Events 中断设备操作集

六、用户态测试代码(可直接编译)

1. H2C 写入示例

2. C2H 读取示例

3. Events 中断等待示例

七、飞腾D2000 + Reworks 常见问题

1. MSI 中断不触发

2. 只能进入一次中断

3. read/write 失败

4. 数据异常/乱码

八、总结


一、XDMA 适配准备

1. 设计原理

本方案基于 Reworks 操作系统,实现 飞腾D2000 + FPGA PCIe XDMA 驱动适配与功能验证。

  • 硬件链路:FPGA <=> PCIe <=> 飞腾D2000
  • XDMA 核心功能:高速数据读写、数据搬移、MSI 中断
  • 对外提供三类字符设备:
  • /dev/xdma0_h2c_0:主机到卡(写通道)
  • /dev/xdma0_c2h_0:卡到主机(读通道)
  • /dev/xdma0_events_0:中断事件通道

数据通路:

CPU <=> PCIe <=> XDMA <=> AXI <=> 双口RAM(64KB)

硬件设计和reworks系统下XDMA成功适配如下:

2. 硬件信息

  • 厂商ID:0x10ee
  • 设备ID:0x7014
  • BAR0:0x58200000(寄存器空间)
  • BAR1:0x58300000(64KB 数据搬移空间)
  • 中断号:irq_line = 88
  • 数据位宽:64bit
  • 最大传输:64KB

二、XDMA 功能与调用流程

1. C2H 读操作(FPGA → 主机)

调用流程:

read() → char_sgdma_read() → sgdma_read_write()

C
static ssize_t char_sgdma_read(void *file, char __user *buf, size_t count)
{
    return char_sgdma_read_write(file, buf, count, 0);
}

2. H2C 写操作(主机 → FPGA)

调用流程:

write() → char_sgdma_write() → sgdma_read_write()

C
static ssize_t char_sgdma_write(void *file, const char __user *buf, size_t count)
{
    return char_sgdma_read_write(file, buf, count, 1);
}

3. Events 中断事件(MSI)

  • 仅支持 read 操作
  • FPGA 触发 usr_irq → 驱动进入 ISR → 唤醒等待队列 → 用户态 read 返回
  • 用于异步事件通知、数据就绪提醒

三、驱动文件结构

文件名

功能说明

xdma_mod.c

驱动入口、PCI 枚举、设备初始化

libxdma.c

XDMA 核心库、中断处理、BAR 操作、SG-DMA

cdev_sgdma.c

H2C/C2H 字符设备 fops 实现

cdev_events.c

中断事件字符设备 fops 实现

cdev_ctrl.c

控制通道设备实现

xdma_test.c / usrlnit.c

用户态测试 Demo、驱动初始化

四、Reworks + 飞腾D2000 BSP 适配流程

1. 环境确认

  • 平台:飞腾D2000(ARM64)
  • 系统:Reworks
  • FPGA:Xilinx XDMA PCIe IP
  • 模式:AXI4 Memory Mapped

2. BSP 配置要点

  1. 开启 PCIe 驱动支持
  1. 开启 MSI 中断(飞腾 + Reworks 必须使能)
  1. 配置 BAR 空间与地址
  1. 配置中断触发方式:边沿触发

3. PCI 设备匹配配置

C
static struct pci_dev pci_xdma = {
    .irq      = 60,
    .no_msi   = 0,
    .devfn    = PCI_DEVEN(0, 0),
    .vendor   = 0x10ee,
    .device   = 0x7014,
};

XDMA+FPGA配置如下:

3.1  XDMA简介

是一种高性能的数据传输技术,它是由PCI-SIG(Peripheral Component Interconnect Special Interest Group)开发的。XDMA代表可扩展的直接内存访问(eXtensible Direct Memory Access),它允许设备直接访问系统内存,而无需通过CPU进行中介。这种直接内存访问技术可以提高数据传输的效率和吞吐量,减少CPU的负载,从而提升系统的性能。XDMA通常用于高性能计算、数据中心和网络设备等领域,可以加快数据传输速度,提高系统的响应能力。 

xdma 是 xilinx 提供的 Pcie 总线桥的IP核,类似于硬件的透传模块;该 ip 核主要作用是将pcie总线转换成axi总线,可以通过该模块直接操作 axi 总线上设备寄存器。模块最新好像可以支持 pcie x16 接口。当前介绍的只支持 x4。

3.2  Pcie 基础设置

分成两个部分,具体大致如下:

注意:其中DMA 功能选择:内存映射功能和流式传输功能;内存映射功能,即dma访问内存的方式间接获取数据,流式即dma直接访问设备的传输FIFO,从对列中直接拿数据。

3.3  Pcie 总线标准硬件协议设置

这里主要是配置

3.4  Pcie BAR 内存映射设置

该内存映射主要是axi总线映射到bar空间的地址,这样便可以通过pcie 直接操作bar空间的地址从而操作axi总线地址设备。

3.5 Pcie 总线中断功能配置

配置内容:

(1)用户中断总线宽度个数,即表示该 ip 核最高支持的中断个数;

(2)中断机制,该中断机制分成 INTx 和 MSI 两种方式;INTx 一种类型仅支持一个用户中断,当前模块 MSI 最多可支持 16 (32) 个用户中断;(INTx 传统中断(INTA、INTB、INTC、INTD),非MSI中断,PCI设备使用INTx中断请求的方式与电平触发类似,而 MSI/MSI-X 中断请求的方式与边沿触发方式类似,是通过直接写内存进行触发中断)

(3)MSI capability 若是选择了该项, MSI-X capability 就必须关闭;

3.6 pcie 自带dma配置

  1. dma 通道配置,分成了读写通道配置 dma 的数量;

  2. Number of Request IDs for Read (Write) channe:每个通道允许最大读写通道个数;

3.7 引脚接口介绍

主要介绍一下各个引脚的功能;

XDMA 中断模式补充说明

3.8  设计概述

本文补充一种基于XDMA中断模式的PCIE上位机与FPGA数据交互架构,实现PCIE X8测速试验,同步提供完整工程源码、QT上位机源码及Vivado工程,适用于Xilinx系列FPGA,可快速上手PCIE通信开发,无需深入掌握复杂的PCIE协议。

3.9  数据交互流程

本架构以图像数据传输为例,完整数据流向如下:

1. QT上位机实时截取主机屏幕图片,将图片数据通过PCIE总线发送至FPGA开发板;

2. FPGA侧XDMA IP核接收数据后,将其缓存至DDR3,缓存完成后产生中断信号;

3. 中断信号通过AXI-GPIO发送至FDMA控制器,通知其从DDR3读取数据;

4. FDMA读取数据后,送入FPGA逻辑进行处理(本设计采用数据回环,可扩展为图像缩放、增强、识别等复杂处理);

5. 数据处理完成后,FDMA将其写回DDR3缓存;

6. XDMA从DDR3读取处理后的数据,通过PCIE总线反馈至QT上位机;

7. QT上位机接收数据并显示处理结果,同时完成PCIE X8速率测试。

3.10 XDMA中断模式

使用普通inax中断还是msi中断?需要FPGA那边使能

本设计的关键在于我们编写了一个 xdma_inter.v 的XDMA中断模块。该模块用来配合驱动处理中断,xdma_inter.v 提供了AXI-LITE 接口,上位机通过访问 user 空间地址读写 xdma_inter.v 的寄存器。该 模块 在 user_irq_req_i 输入的中断位,寄存中断位号,并且输出给 XDMA IP ,当上位机的驱动响应中断的时候,在中断里面写 xdma_inter.v 的寄存器,清除已经处理的中断。

另外本方案中通过 AXI-BRAM 来演示用户 user 空间的读写访问测试。

该方案只适用于Xilinx系列FPGA,一并提供了XDMA的安装驱动和QT上位机源代码,省去了使用XDMA繁琐的驱动寻找和上位机软件开发的不知所措,并以搭建好vivado工程,省去了不知道如何使用XDMA的尴尬,使得PCIE的使用变得简单易上手,而不用关心其复杂的PCIE协议;由于我的开发板只支持PCIE X8,所以提供的代码是PCIE X8架构,若需要PCIE X1、 X2、 X8、 X16、 X32的朋友,可自行修改本工程,也可关注我,我会实时发布新的工程。

本工程实现基础的PCIE通信,和QT上位机之间进行测速试验。

3.11 图像输出扩展

除上位机显示外,本方案还支持图像HDMI输出:FDMA控制器收到XDMA中断信号、读取DDR3中的图片数据后,将图像信息送入VGA时序数据总线,生成1920X1080@60Hz分辨率的VGA视频流;视频流再传入HDMI发送模块,将RGB数据转换为HDMI差分信号,通过HDMI线缆输出至显示器,实现图像实时预览。

3.12 核心模块设计(xdma_inter.v)

本设计的核心是自主编写的xdma_inter.v中断模块,用于配合驱动完成中断处理,其核心功能如下:

  • 提供AXI-LITE接口,上位机可通过访问user空间地址,读写该模块的寄存器;

  • 对user_irq_req_i输入的中断位进行寄存,并将中断位号输出至XDMA IP核;

  • 上位机驱动响应中断后,通过写入该模块寄存器的方式,清除已处理的中断标志,确保中断可重复触发。

XDMA框图如下:

3.13 XDMA IP核心特性说明

Xilinx官方提供的DMASubsystem for PCIExpress IP,是一款高性能、可配置的SG模式DMA,支持PCIE2.0、PCIE3.0协议,核心特性如下:

  • XDMA属于SGDMA(散射-聚集DMA),而非Block DMA;SG模式下,主机将待传输数据组成链表,通过BAR将链表首地址发送给XDMA,XDMA根据链表结构依次完成传输任务;

  • 数据传输接口二选一:AXI4接口适用于大数据量异步传输,通常搭配DDR使用;AXI4-Stream接口适用于低延迟数据流传输;

  • 可选接口配置:AXI4-Lite Master用于实现PCIE BAR地址与AXI4-lite寄存器地址的映射,可读写用户逻辑寄存器;AXI4-Lite Slave用于将XDMA内部寄存器开放给用户逻辑,不映射至BAR;AXI4 Bypass接口用于PCIE直通用户逻辑访问,实现低延迟传输(目前部分场景采用X16链路,分为两个X8通道)。

3.14 中断模式说明

XDMA支持普通中断与MSI中断两种模式,具体使用哪种模式,需在FPGA端完成使能配置,结合前文Reworks系统适配要求,MSI中断需在BSP中开启GIC配置、确认中断号一致性,才能确保中断正常触发。

3.15 工程补充说明

  • 适用范围:仅适用于Xilinx系列FPGA,提供XDMA安装驱动、QT上位机源码及现成Vivado工程,省去驱动寻找、上位机开发及XDMA配置的繁琐流程;

  • 链路配置:因开发板限制,本工程默认采用PCIE X8架构,需PCIE X1、X2、X16、X32架构的可自行修改工程,或关注后续更新;

  • 额外测试:方案通过AXI-BRAM演示user空间的读写访问测试,可直接用于验证驱动与硬件的通信稳定性。

3.16  衔接前文:Reworks系统下XDMA BSP适配延伸

结合前文飞腾D2000 + Reworks的XDMA适配流程,上述基于中断模式的XDMA架构,在Reworks系统下进行BSP适配时,需重点完成以下配置与工作,确保架构正常运行:

下文将详细拆解Reworks系统下XDMA BSP的完整适配流程、核心配置要点及驱动开发重点,衔接前文适配经验,实现从架构设计到系统适配的全流程落地。

4. BAR 数量与大小定义

C
#define XDMA_BAR_NUM        2
#define XDMA_BAR_SIZE       0x8000UL
#define MAX_SIZE            (64*1024)

5. MSI 中断适配(Reworks/GIC)

C
#ifdef USE_MSI
msi_int_ack(xdev->irq_line);
#endif

shared_int_install(xdev->irq_line, (void (*)(void *))xdma_isr, xdev);
gic_set_edged_trig(xdev->irq_line);
int_enable_pic(xdev->irq_line);

6. XDMA 驱动初始化

C
int fpga_xdma_init(void)
{
    static int xdma_init_flag = 0;
    if (xdma_init_flag == 1)
        return 0;

    // PCI 初始化
    xdma_pci_init();

    // 创建内存池
    xdma_req_pool_id = req_pool_create(32);

    // 设备探测
    probe_one();

    xdma_init_flag = 1;
    return 0;
}

在主函数 UserInit 中调用:

C
void UserInit(void)
{
    fpga_xdma_init();
}

五、字符设备 fops 实现

1. SGDMA(H2C/C2H)操作集

C
static const struct file_operations sgdma_fops = {
    .open    = char_sgdma_open,
    .close   = char_sgdma_close,
    .read    = char_sgdma_read,
    .write   = char_sgdma_write,
    .ioctl   = char_sgdma_ioctl,
    .llseek  = char_sgdma_llseek,
};

2. 偏移控制(FIOSEEK)

C
case FIOSEEK:
    rv = char_sgdma_llseek(xcdev, arg, 0);
    break;

3. Events 中断设备操作集

C
static const struct file_operations events_fops = {
    .open    = char_open,
    .close   = char_close,
    .read    = char_events_read,
    .poll    = char_events_poll,
};

六、用户态测试代码(可直接编译)

1. H2C 写入示例

C
#define MAX_SIZE (64*1024)
void writexdma(unsigned int addr, int value)
{
    static int wrFd = -1;
    uint32_t memory[MAX_SIZE] = {0};

    if (wrFd < 0)
        wrFd = open("/dev/xdma0_h2c_0", O_RDWR, 0777);

    if (addr >= MAX_SIZE)
        return;

    memory[addr] = value;
    ioctl(wrFd, FIOSEEK, addr);
    write(wrFd, &memory[addr], sizeof(uint32_t));
}

2. C2H 读取示例

C
int readxdma(int addr)
{
    static int rdFd = -1;
    uint32_t memory[MAX_SIZE] = {0};

    if (rdFd < 0)
        rdFd = open("/dev/xdma0_c2h_0", O_RDWR, 0777);

    ioctl(rdFd, FIOSEEK, addr);
    read(rdFd, &memory[addr], sizeof(uint32_t));
    return memory[addr];
}

3. Events 中断等待示例

C
int event_test(void)
{
    uint32_t val = 0;
    int fd = open("/dev/xdma0_events_0", O_RDONLY);

    // 阻塞等待中断触发
    read(fd, &val, sizeof(val));
    close(fd);
    return val;
}

七、飞腾D2000 + Reworks 常见问题

1. MSI 中断不触发

  • 检查 GIC 中断配置
  • 确认硬件中断号与驱动一致
  • 检查 FPGA 端 msi_enable 使能

2. 只能进入一次中断

  • 未清除中断标志位
  • 中断配置为电平触发,需改为边沿触发

3. read/write 失败

  • 检查/dev/xdma* 设备节点是否生成
  • 检查地址是否越界(0 ~ 64KB)
  • 检查文件权限与打开模式

4. 数据异常/乱码

  • 检查 AXI 位宽、PCIe 链路配置
  • 地址建议按 8 字节对齐

八、总结

本文完整实现 飞腾D2000 + Reworks 平台下 XDMA PCIe 驱动的适配与验证,包含:

  • PCIe 设备枚举与 BAR 映射
  • MSI 中断配置与处理
  • H2C/C2H 高速数据通道
  • Events 异步中断事件
  • 用户态可直接运行的测试代码

所有代码均经过实际项目验证,适用于国产化迁移、FPGA 加速、高速数据采集、PCIe 驱动开发等场景。

配套资源(私信)

  • XDMA 驱动源码
  • 用户态测试工程
  • Vivado XDMA IP 配置参考
  • BSP 配置说明

提示:需要注意的是,具体的适配流程和配置工作可能会因Reworks版本和硬件平台的不同而有所差异,需要根据实际情况进行调整和修改。此外,还需要参考xdma驱动的文档和示例代码,以确保正确地适配和配置xdma驱动。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐