1. Synopsys PCIe EDMA驱动概述
在PCIe设备开发中,DMA(直接内存访问)引擎是提升数据传输效率的核心组件。Synopsys提供的PCIe EDMA(Enhanced DMA)解决方案被广泛应用于各类高性能外设中,其驱动实现的质量直接影响设备的吞吐量和稳定性。
我曾在多个FPGA项目中集成过Synopsys的PCIe EDMA控制器,发现其驱动数据结构的设计颇有讲究。不同于普通的DMA控制器,EDMA支持多通道、分散-聚集(Scatter-Gather)传输、优先级调度等高级特性,这就要求驱动开发者必须透彻理解其内部数据结构才能充分发挥硬件性能。
2. EDMA核心数据结构解析
2.1 通道控制块(Channel Control Block)
每个EDMA通道都对应一个CCB数据结构,这是驱动与硬件交互的关键桥梁。典型的CCB包含以下字段:
c复制struct edma_ccb {
u32 ctrl; // 控制寄存器
u32 src_addr_lo; // 源地址低32位
u32 src_addr_hi; // 源地址高32位(支持64位寻址)
u32 dest_addr_lo; // 目的地址低32位
u32 dest_addr_hi; // 目的地址高32位
u32 xfer_size; // 传输字节数
u32 sg_addr; // 散列表地址(SG模式使用)
u32 intr_status; // 中断状态寄存器
};
注意:实际项目中需要根据具体EDMA版本调整结构体对齐方式,我曾遇到过因结构体padding导致寄存器错位的问题。
2.2 散列表描述符(Scatter-Gather Descriptor)
当启用SG传输时,驱动需要构建描述符链表。每个描述符代表一个不连续的内存块:
c复制struct edma_sg_desc {
u32 src_addr;
u32 dest_addr;
u32 size; // 本段传输大小
u32 next_desc; // 下一个描述符地址
u32 ctrl; // 控制标志位
};
在Linux驱动实现中,通常会通过dma_alloc_coherent()分配连续的DMA内存来存放这些描述符。一个常见错误是忘记设置描述符链表的末尾标志(CTRL_EOL),这会导致DMA引擎无限循环。
2.3 全局寄存器映射
驱动初始化时需要映射的硬件寄存器包括:
| 寄存器名称 | 偏移地址 | 功能描述 |
|---|---|---|
| EDMA_VERSION | 0x000 | 控制器版本号 |
| EDMA_GLOBA |
