1. DMA 基础概念
1.1 DMA 的定义
DMA(Direct Memory Access,直接存储器访问) 是一种允许硬件设备(如网卡、声卡、存储控制器、摄像头接口等)在不经过 CPU 干预的情况下,直接与系统内存进行批量数据交换的技术。DMA 控制器(DMAC)作为独立的总线主控器,接管总线控制权,完成从源地址到目的地址的数据搬运。
核心要点:DMA 的本质是“硬件级数据通道”,将 CPU 从繁重的数据拷贝任务中解放出来,使其专注于计算与控制逻辑。
1.2 DMA 与 CPU 数据搬运的区别
传统的数据搬运由 CPU 通过 PIO(Programmed I/O,程序控制输入输出) 模式完成:CPU 逐字(或逐字节)从外设读取数据,再写入内存。DMA 模式则完全由硬件自动完成。下表从多个维度对比两种方式:
| 对比维度 | CPU 搬运(PIO) | DMA 搬运 |
|---|---|---|
| 数据路径 | 外设 → CPU 寄存器 → 内存 | 外设 → 内存(直通) |
| CPU 占用率 | 100%(搬运期间无法执行其他任务) | 仅初始化时占用,搬运期间可并行执行其他任务 |
| 吞吐量 | 受限于 CPU 主频与寄存器宽度,通常较低 | 接近总线带宽,适合高速批量传输 |
| 延迟 | 每字一次中断或轮询,延迟累积大 | 仅传输完成一次中断,延迟可控 |
| 适用场景 | 小数据量、低频控制信号(如 GPIO 状态读取) | 大数据块、高速流(如网络帧、音频流、视频帧) |
| 硬件复杂度 | 无需额外 DMA 控制器 | 需要 DMAC 或集成 DMA 引擎 |
经验法则:在嵌入式 Linux 驱动中,单次传输超过 64 字节时,DMA 的收益就开始明显超过 PIO。对于 1 KB 以上的数据块,DMA 通常能降低 CPU 占用率 90% 以上。
1.3 DMA 在嵌入式系统中的作用
嵌入式系统对实时性、功耗和吞吐量有严苛要求,DMA 在以下方面发挥关键作用:
- 降低 CPU 负载:CPU 只需配置 DMA 描述符并等待完成中断,无需逐字参与拷贝,从而释放算力用于协议栈、算法或 UI 渲染。
- 提升数据吞吐量:DMA 利用总线突发传输(burst transfer),一次请求可搬运多个数据字,充分利用总线带宽。
- 减少中断频率:PIO 模式下每传输一个字可能触发一次中断;DMA 模式下整批传输完成才触发一次中断,减少上下文切换开销。
- 支持外设与内存间直接交互:例如摄像头传感器通过 DMA 直接将图像数据写入帧缓冲区,无需 CPU 逐行拷贝。
- 实现低功耗:CPU 在 DMA 搬运期间可进入休眠或低功耗状态,由 DMAC 独立完成数据移动,显著降低系统功耗。
1.4 DMA 传输流程概览
下图展示了一次典型 DMA 传输的完整流程,包含 CPU、DMA 控制器、外设和内存四方的交互关系:
1.5 DMA 的关键技术指标
在嵌入式系统选型与驱动开发中,以下 DMA 指标直接影响系统性能:
- 通道数:DMAC 支持的独立 DMA 通道数量,决定可同时服务的外设数量。
- 传输宽度:单次传输的数据位宽(8/16/32/64 位),影响单次搬运效率。
- 突发传输长度:一次总线仲裁请求中连续传输的数据单元数(如 4/8/16 次突发),越长则总线利用率越高。
- 地址递增模式:支持固定地址(外设 FIFO)、递增地址(内存缓冲区)、或二维/链表模式。
- 描述符链:是否支持硬件自动加载下一个描述符,实现无需 CPU 干预的连续多段传输。
常见误区:DMA 并非“零 CPU 开销”。CPU 仍需参与描述符配置、中断处理和错误恢复。在极短传输(< 32 字节)场景下,DMA 的初始化开销可能超过 PIO,需根据实际数据量权衡。
1.6 嵌入式系统中常见的 DMA 架构
不同 SoC 厂商的 DMA 实现各有差异,但主流架构可归纳为以下三类:
| 架构类型 | 代表平台 | 特点 | 适用场景 |
|---|---|---|---|
| 独立 DMAC | STM32、NXP i.MX | 专用 DMA 控制器,多通道,支持链式描述符 | 通用嵌入式系统,外设种类多 |
| 总线矩阵 DMA | ARM Cortex-M 系列 | 集成在总线矩阵中,支持内存到内存、外设到内存 | 低功耗 MCU,中等数据吞吐量 |
| IOMMU/SMMU + DMA | ARM Cortex-A + Linux | 通过 IOMMU 实现设备虚拟地址映射,支持安全隔离 | 高性能嵌入式 Linux,多进程共享 DMA 缓冲区 |
1.7 本章小结
DMA 是嵌入式系统中实现高性能、低延迟、低功耗数据搬运的核心硬件机制。与 CPU 逐字搬运的 PIO 模式相比,DMA 将 CPU 从数据拷贝中解放出来,使其专注于控制与计算。理解 DMA 的基本定义、与 CPU 搬运的差异、在系统中的作用以及关键指标,是后续深入学习 Linux DMA 驱动框架(dmaengine、DMA API、描述符管理)的基石。