1. DMA 概述:工作原理、对比、优势与应用场景
1.1 DMA 工作原理
直接存储器访问(Direct Memory Access, DMA)是一种允许硬件子系统(外设或内存)直接读写系统内存,而无需 CPU 介入的机制。DMA 控制器(DMAC)作为总线上的主设备,接管总线控制权,完成数据搬运任务。
核心思想:CPU 只需启动传输,DMA 控制器独立完成数据搬运,传输完成后通过中断通知 CPU。
1.2 DMA 与 CPU 数据搬运对比
传统 CPU 搬运数据采用 PIO(Programmed I/O)模式,CPU 逐字读取源数据并写入目的地。DMA 模式则将搬运任务卸载给专用硬件。两者关键差异如下:
| 对比维度 | CPU 搬运(PIO) | DMA 搬运 |
|---|---|---|
| 执行主体 | CPU 核心 | DMA 控制器(DMAC) |
| 总线占用 | CPU 全程占用总线 | DMAC 周期窃取或突发模式占用 |
| CPU 利用率 | 100% 被搬运任务占用 | 仅配置和中断处理阶段占用(通常 <5%) |
| 吞吐量 | 受限于 CPU 频率和指令执行速度 | 接近总线理论带宽,通常高 5~10 倍 |
| 延迟抖动 | 受中断、调度影响较大 | 硬件流水线,延迟稳定可预测 |
| 适用场景 | 小数据量(<64 字节)、控制寄存器访问 | 大数据块(≥1 KB)、流式外设、内存拷贝 |
经验法则:当单次传输量超过 256 字节时,DMA 的启动开销即可被传输收益覆盖。对于嵌入式 Linux 中的网络收包、存储 I/O、显示刷新等场景,DMA 是标配选择。
1.3 DMA 传输优势
DMA 在嵌入式系统中带来的核心优势可归纳为以下四点:
- CPU 卸载:将重复性数据搬运从 CPU 卸载到专用硬件,CPU 可并行执行协议栈、应用逻辑或控制任务。
- 高吞吐量:DMA 控制器以硬件状态机运行,每个时钟周期可完成一次总线传输,吞吐量接近总线物理极限。
- 低延迟与确定性:硬件传输路径无操作系统调度抖动,适合音频、视频等实时流处理。
- 功耗优化:CPU 在 DMA 传输期间可进入低功耗模式(WFI/WFE),显著降低系统功耗。
1.4 典型应用场景
DMA 在嵌入式 Linux 系统中无处不在,以下列出最常见的六大应用场景:
| 应用场景 | 传输方向 | 典型数据量 | 实时性要求 |
|---|---|---|---|
| 网络数据包收发 | 外设 → 内存 / 内存 → 外设 | 64B ~ 9KB(Jumbo Frame) | 中 |
| 存储设备读写(eMMC/SD/NVMe) | 外设 ↔ 内存 | 512B ~ 1MB(块设备) | 低 |
| 显示帧缓冲刷新 | 内存 → 显示控制器 | 几 MB ~ 几十 MB(帧缓冲) | 高(vsync 同步) |
| 音频流播放/录制 | 内存 → I2S / I2S → 内存 | 每周期 4~256 样本 | 高(无 XRUN) |
| 摄像头图像采集 | CSI/并行接口 → 内存 | VGA ~ 4K 帧(几 MB) | 高(帧率稳定) |
| 硬件加速器(加密/编解码) | 内存 ↔ 加速器 | 几 KB ~ 几 MB | 中 |
注意:并非所有外设都适合 DMA。对于 SPI 或 UART 等低速外设(< 1 Mbps),DMA 的配置开销可能超过 PIO 传输时间,此时应使用 CPU 搬运或 FIFO 模式。
1.5 DMA 传输模式分类
根据传输触发方式和数据流向,DMA 传输可分为以下三种基本模式:
- 内存到内存(Mem2Mem):源和目的都是内存地址,由软件显式触发。常用于大块数据拷贝、内存清零、CRC 计算等。
- 内存到外设(Mem2Dev):从内存读取数据发送到外设 FIFO。典型场景:显示刷新、音频播放、SPI 发送。
- 外设到内存(Dev2Mem):从外设 FIFO 读取数据写入内存。典型场景:网络收包、摄像头采集、音频录制。
关键概念:在 Linux dmaengine 框架中,
dma_slave_config 结构体用于配置外设方向(DMA_DEV_TO_MEM / DMA_MEM_TO_DEV),而 DMA_MEM_TO_MEM 则通过 dma_async_memcpy 接口实现。
1.6 本章小结
DMA 是嵌入式系统中实现高性能数据搬运的核心硬件机制。通过将重复性传输任务卸载到专用 DMA 控制器,CPU 得以解放出来处理更复杂的控制逻辑和协议栈。理解 DMA 的工作原理、与 CPU 搬运的差异、典型应用场景以及三种传输模式,是后续学习 dmaengine 接口和描述符链管理的基础。