1. DMA 基础概念

1.1 DMA 工作原理

直接存储器访问(Direct Memory Access, DMA)是一种允许硬件设备直接与系统内存交换数据,而无需 CPU 逐字节干预的数据传输机制。DMA 控制器(DMAC)作为总线上的独立主控设备,在获得总线控制权后,负责完成从源地址到目的地址的数据搬运。

核心要点:DMA 的本质是将数据搬运任务从 CPU 卸载给专用硬件控制器,使 CPU 能够专注于计算与控制逻辑。

一次典型的 DMA 传输流程包含以下步骤:

  1. CPU 配置 DMA 控制器:设置源地址、目的地址、传输长度、传输方向(内存→外设、外设→内存、内存→内存)以及触发方式。
  2. DMA 请求与仲裁:外设或软件发起 DMA 请求,DMAC 向总线仲裁器申请总线控制权。
  3. 总线控制权移交:CPU 释放总线,DMAC 获得总线主控权,开始搬运数据。
  4. 数据传输执行:DMAC 按配置逐字或逐块搬运数据,每完成一个单元更新地址计数器。
  5. 传输完成中断:当传输计数器归零,DMAC 向 CPU 发送中断信号,通知传输结束。
工程提示:在 Linux 内核中,dmaengine 子系统封装了上述流程,驱动开发者通过 dma_request_channel()、dmaengine_prep_slave_sg() 等 API 即可完成配置,无需直接操作 DMAC 寄存器。
DMA 传输流程示意图 CPU 配置 DMAC DMA 请求 & 仲裁 总线控制权移交 数据传输执行 传输完成中断 说明: 整个传输过程中,CPU 仅在配置阶段和中断处理阶段参与,数据搬运完全由 DMAC 独立完成。 外设 (SPI/UART) DMA 控制器 系统内存

1.2 DMA 与 CPU 数据搬运对比

传统 PIO(Programmed I/O)模式下,CPU 需要逐字从外设读取数据并写入内存,或反向操作。DMA 模式则将这一重复性工作交给专用硬件。下表从多个维度对比两种方式:

对比维度 CPU 直接搬运 (PIO) DMA 搬运
CPU 占用率 100%,搬运期间无法执行其他任务 仅配置和中断阶段占用,传输期间可并行执行其他任务
传输速率 受限于 CPU 主频与指令执行速度 可达总线带宽上限,通常比 PIO 快 5~10 倍
适用数据量 小数据量(< 64 字节) 大数据量(≥ 64 字节),数据量越大优势越明显
硬件复杂度 无需额外硬件 需要 DMA 控制器及总线仲裁支持
延迟 低延迟,CPU 立即响应 存在 DMA 配置和总线仲裁延迟
Cache 一致性 天然一致(CPU 直接操作) 需软件维护 Cache 一致性(dma_alloc_coherent / dma_map_single)
常见误区:并非所有场景都适合 DMA。对于小于 64 字节的短数据,DMA 的配置开销可能超过 PIO 的传输时间,此时使用 PIO 反而更高效。驱动开发者应根据实际数据量动态选择传输方式。
CPU 搬运 vs DMA 搬运对比图 CPU 直接搬运 (PIO) CPU 逐字读取外设数据 → 写入内存 CPU 占用率:100% 传输速率:受 CPU 主频限制 DMA 搬运 DMAC 从外设读取数据 → 写入内存 CPU 占用率:仅配置 + 中断阶段 传输速率:接近总线带宽 关键差异: DMA 将 CPU 从重复的数据搬运中解放出来,使其可以并行执行协议解析、算法计算等高价值任务。 CPU 占用: 100% CPU 占用: ~5% 速率: 低 速率: 高

1.3 DMA 传输优势与适用场景

DMA 的核心优势在于 CPU 卸载 和 高吞吐,这使得它在以下场景中成为不可或缺的技术:

  • 高速外设数据流:如以太网 MAC、USB 控制器、SD/MMC 主机控制器、高速 ADC/DAC。这些设备的数据速率可达数百 Mbps 甚至 Gbps,PIO 模式无法满足。
  • 多媒体数据处理:摄像头传感器数据采集、音频 I2S 流、显示控制器帧缓冲更新。DMA 可保证实时数据流不丢帧。
  • 存储子系统:NVMe、eMMC、UFS 等存储设备的读写操作,DMA 用于搬运块数据。
  • 内存到内存拷贝:大型数据缓冲区复制、加密/解密引擎的数据输入输出、图像处理管线中的缓冲区传递。
  • 实时系统:在确定性要求高的场景中,DMA 可避免 CPU 因频繁中断而导致的调度抖动。
性能数据参考:在 ARM Cortex-A72 @ 2.0GHz 平台上,PIO 方式搬运 1MB 数据约需 800μs(CPU 满载),而 DMA 方式仅需 120μs(CPU 占用 < 5%),吞吐量提升约 6.7 倍。
DMA 适用场景架构图 DMA 控制器 以太网 MAC USB 控制器 SD/MMC 主机 摄像头传感器 音频 I2S 显示控制器 适用场景特征: 高数据速率(≥ 10MB/s)、大数据块(≥ 64 字节)、实时性要求高、CPU 需要并行处理其他任务。

1.4 DMA 传输模式分类

根据数据传输的触发方式和组织形式,DMA 传输可分为以下三种主要模式:

传输模式 触发方式 典型应用 Linux dmaengine 接口
单次传输 软件显式启动 内存到内存拷贝、一次性数据块搬运 dmaengine_submit() + dma_async_issue_pending()
循环传输 硬件事件自动循环 音频流、摄像头数据流、连续 ADC 采样 dmaengine_prep_dma_cyclic()
散聚传输 链表描述符自动执行 网络数据包收发、文件系统块 I/O dmaengine_prep_slave_sg()
工程建议:在编写驱动时,优先使用散聚传输(SG)模式。它允许 DMA 控制器自动遍历描述符链表,无需 CPU 在每次传输后重新配置,极大降低中断频率,提升整体吞吐量。
DMA 传输模式对比 单次传输 CPU 配置 → DMAC 执行一次 → 中断 适合:一次性数据块 循环传输 DMAC 自动循环搬运,无中断 适合:音频/视频流 散聚传输 (SG) 描述符链表自动执行 适合:网络/存储 I/O 模式选择原则: 数据流连续且周期固定 → 循环传输;数据分散在多个不连续缓冲区 → 散聚传输;简单一次性拷贝 → 单次传输。