2. DMA 硬件架构:DMA 控制器内部结构

DMA 控制器是系统总线上一个独立的总线主控设备。理解其内部结构是驱动开发的基础,直接决定了描述符链的编排方式和带宽优化策略的选择。本节深入剖析 DMA 控制器的三大核心模块:通道、请求仲裁和地址发生器,并分析其与系统总线的连接拓扑。

2.1 DMA 控制器内部核心模块

一个典型的 DMA 控制器内部由多个并行工作的硬件模块组成。下图展示了其宏观架构:

DMA 控制器内部核心模块架构 DMA 控制器内部核心模块架构 DMA 控制器 通道 (Channels) 通道 0 (CH0) 通道 1 (CH1) 通道 2 (CH2) 通道 3 (CH3) (最多 32 通道) 请求仲裁 (Arbiter) 固定优先级 / 轮询 / 混合 地址发生器 (AGU) 源/目的地址 + 增量 系统总线接口 (Bus Master I/F) AHB / AXI / PCIe 读/写地址通道 数据通道

2.2 通道 (Channel)

通道是 DMA 控制器中执行一次数据传输任务的基本硬件单元。每个通道独立维护一组配置寄存器,包括:

  • 源地址寄存器 (SAR):存放数据源地址。
  • 目的地址寄存器 (DAR):存放数据目的地址。
  • 传输计数寄存器 (CTL/NDT):记录剩余待传输的数据量。
  • 控制寄存器 (CCR):配置传输方向、数据宽度、突发大小、中断使能等。
  • 描述符指针寄存器 (LLP):用于链式传输时指向下一个描述符。
驱动开发要点: 通道数量决定了系统能同时处理的 DMA 传输任务数。在驱动中,通常使用一个通道池来管理这些硬件资源,避免多个软件模块冲突。

2.3 请求仲裁 (Arbiter)

当多个通道同时请求总线访问时,仲裁器决定哪个通道获得总线控制权。常见的仲裁策略包括:

仲裁策略 工作原理 适用场景 带宽影响
固定优先级 通道编号越小,优先级越高(CH0 > CH1 > ...) 实时性要求高的关键数据流 高优先级通道可能饿死低优先级通道
轮询 (Round-Robin) 所有通道轮流获得总线使用权 多个通道带宽需求相近 带宽分配公平,但延迟可能增加
混合策略 高优先级通道使用固定优先级,其余使用轮询 既有实时流又有批量数据传输 兼顾实时性和公平性
避坑指南: 在驱动初始化时,务必根据业务场景配置仲裁策略。例如,音频 DMA 通道应设置为高优先级,而文件系统 DMA 通道可使用轮询。错误的仲裁配置会导致音频断流或存储性能下降。

2.4 地址发生器 (AGU)

地址发生器负责在每次数据传输后自动更新源地址和目的地址。其核心能力决定了 DMA 能否处理复杂的内存布局:

  • 固定地址模式:地址不变,用于访问 FIFO 或外设数据寄存器。
  • 增量模式:地址按数据宽度递增,用于连续内存块传输。
  • 循环缓冲模式:地址在指定范围内循环,用于音频环形缓冲区。
  • 二维/三维地址跳转:支持行/帧步进,用于图像数据块传输。
地址发生器工作模式示意 地址发生器 (AGU) 工作模式 固定地址模式 Addr = 0x4000_0000 Addr = 0x4000_0000 Addr = 0x4000_0000 增量模式 Addr = 0x1000_0000 Addr = 0x1000_0004 Addr = 0x1000_0008 循环缓冲模式 Addr = 0x2000_0000 Addr = 0x2000_0100 Addr = 0x2000_0000 AGU 在每个时钟周期内完成地址计算 支持源地址和目的地址独立配置模式 二维模式:行步长 + 帧步长,用于图像/矩阵

2.5 DMA 与系统总线的连接方式

DMA 控制器作为总线主控设备,通过系统总线直接访问内存和外设。常见的连接拓扑包括:

2.5.1 单总线架构

DMA 控制器、CPU 和所有外设共享一条系统总线(如 AHB)。DMA 传输时,CPU 必须等待总线释放。这种架构简单,但带宽受限,适用于低功耗嵌入式 MCU。

2.5.2 多总线架构 (Multi-Layer Bus Matrix)

DMA 控制器通过独立的 master 端口连接到总线矩阵,可以同时访问多个 slave 设备。例如,DMA 从 SRAM 读取数据的同时,CPU 可以访问 Flash。这种架构显著提升了系统并发性能。

2.5.3 专用 DMA 总线 (DMA Bus)

在高性能 SoC 中,DMA 控制器拥有专用的数据总线,不经过系统总线矩阵,直接连接到内存控制器和高带宽外设(如 GPU、网络控制器)。这种架构延迟最低,带宽最大。

连接方式 典型总线 并发能力 延迟 典型应用
单总线 AHB / APB 低 高 STM32、低功耗 MCU
多总线矩阵 AXI / AHB-Lite 中 中 ARM Cortex-A 系列 SoC
专用 DMA 总线 AXI-Stream / PCIe 高 低 FPGA、GPU、高速网卡
DMA 与系统总线连接拓扑 DMA 与系统总线连接拓扑 单总线架构 CPU DMA 控制器 内存 (SRAM) 外设 (UART/SPI) 共享总线,串行访问 多总线矩阵 CPU DMA 总线矩阵 (Bus Matrix) 交叉开关 SRAM Flash 外设 (USB/ETH) 并行访问,高并发 专用 DMA 总线 CPU DMA 控制器 内存控制器 高速外设 (GPU/NIC) 低延迟,高带宽

2.6 驱动开发中的硬件抽象

在 Linux 内核中,DMA 引擎驱动通过 dma_device 结构体抽象硬件能力。驱动开发者需要填充以下关键字段:

struct dma_device {
    unsigned int    channels;       // 硬件通道数量
    enum dma_cap_mask_t  cap_mask;  // 能力位掩码
    struct list_head  channels;     // 通道链表

    // 通道操作函数
    int (*device_alloc_chan_resources)(struct dma_chan *chan);
    void (*device_free_chan_resources)(struct dma_chan *chan);

    // 描述符操作
    struct dma_async_tx_descriptor *(*device_prep_dma_memcpy)(
        struct dma_chan *chan, dma_addr_t dst, dma_addr_t src,
        size_t len, unsigned long flags);
    struct dma_async_tx_descriptor *(*device_prep_slave_sg)(
        struct dma_chan *chan, struct scatterlist *sgl,
        unsigned int sg_len, enum dma_transfer_direction direction,
        unsigned long flags, void *context);

    // 控制操作
    int (*device_control)(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
                          unsigned long arg);
    enum dma_status (*device_tx_status)(struct dma_chan *chan,
                        dma_cookie_t cookie, struct dma_tx_state *txstate);
    void (*device_issue_pending)(struct dma_chan *chan);
};
关键理解: 硬件架构决定了驱动代码的组织方式。通道数量对应驱动中的通道池大小;仲裁策略影响中断处理优先级;地址发生器能力决定了驱动是否支持 scatter-gather 和 cyclic 传输模式。在编写 DMA 驱动前,务必先阅读芯片参考手册中的 DMA 控制器章节,确认上述硬件参数。