1. DMA 基础概念:CPU 的“数据搬运工”

各位同学,咱们今天正式开讲 DMA。说实话,我做了十几年嵌入式驱动,DMA 这玩意儿几乎天天打交道。你问它有多重要?这么说吧,没有 DMA 的嵌入式系统,就像让一个博士生天天去搬砖——不是不能干,是太浪费了。

1.1 什么是 DMA?

DMA,全称 Direct Memory Access,直接存储器访问。说白了,就是硬件层面专门负责数据搬运的一个独立模块。

我习惯这么跟新人解释:DMA 是一个硬件加速器,它可以在没有 CPU 参与的情况下,把数据从 A 点搬到 B 点。A 点和 B 点可以是内存、外设寄存器、或者内存和外设之间。

核心定义:DMA 是一种允许外设或内存之间直接传输数据的技术,传输过程由 DMA 控制器管理,CPU 只需在传输开始前配置参数,传输完成后接收中断。

你想想看,如果没有 DMA,每次外设有数据要处理,CPU 都得亲自去读寄存器、存内存。一次两次还行,如果数据量大了,比如音频采样、摄像头数据流,CPU 就彻底被绑死了。

1.2 DMA 与 CPU 数据搬运的区别

这个区别,我画个表格你就明白了。

对比维度 CPU 直接搬运 DMA 搬运
执行主体 CPU 核心 DMA 控制器(独立硬件)
CPU 占用 100% 占用,无法做其他事 仅配置和收尾时占用
传输速度 受限于 CPU 主频和指令执行 硬件级并行,通常更快
适用场景 小数据量、低频操作 大数据量、高频、实时流
编程复杂度 简单,直接读写寄存器 需要配置描述符、链表等
功耗 较高(CPU 全速运行) 较低(专用硬件更高效)

举个例子,我记得有一次做音频播放器项目,用 CPU 直接搬运 I2S 数据,结果系统一播放音乐,其他任务全部卡顿。换成 DMA 之后,CPU 占用从 80% 降到了 5%,效果立竿见影。

我的经验:判断是否该用 DMA,有个简单标准——如果数据传输量超过 64 字节,或者传输频率超过 1kHz,就值得考虑 DMA。低于这个阈值,CPU 直接搬反而更快,因为 DMA 配置本身也有开销。

1.3 DMA 在嵌入式系统中的作用

DMA 在嵌入式系统里,说白了就干三件事:

  • 解放 CPU——让 CPU 从繁琐的数据搬运中解脱出来,去处理更重要的计算和控制逻辑。
  • 提高吞吐量——DMA 可以背靠背传输,一个时钟搬一个数据,效率远高于 CPU 的取指-译码-执行流水线。
  • 降低延迟——特别是对实时性要求高的场景,比如音频、视频、高速 ADC 采样。

我给大家画个图,看看 DMA 在整个系统中的位置。

DMA 在嵌入式系统架构中的位置 CPU 核心 系统总线(AHB / AXI) DMA 控制器 (数据搬运引擎) 内存(SRAM / DDR) 数据缓冲区 外设(UART / SPI / I2S) 数据源 / 目的地 数据传输路径说明 • 实线路径:CPU 通过总线访问内存和外设(控制/配置路径) • 橙色虚线路径:DMA 直接搬运数据(内存 ↔ 内存 / 内存 ↔ 外设) • CPU 只需配置 DMA 描述符,传输过程完全由 DMA 硬件自主完成 图 1-1:DMA 在嵌入式系统架构中的位置与数据流

从图上你能看到,DMA 控制器和 CPU、内存、外设都挂在系统总线上。但关键区别在于:DMA 可以绕过 CPU,直接在内存和外设之间建立数据传输通道。这就是它名字里 "Direct"(直接)的由来。

1.4 什么时候必须用 DMA?

我遇到过不少新手问:是不是所有项目都要上 DMA?当然不是。我总结了几种非用不可的场景:

  • 高速数据流:比如摄像头 OV5640 输出 1080p 视频,每秒几十 MB 的数据量,CPU 根本扛不住。
  • 实时音频:I2S 接口播放音乐,数据必须连续不间断,稍有延迟就是爆音。
  • 多通道同步采集:比如 8 通道 ADC 同时采样,DMA 可以乒乓缓冲,一个缓冲区在传输,另一个在填充。
  • 低功耗场景:CPU 可以进入睡眠模式,DMA 自己干活,完事了再唤醒 CPU。

避坑指南:我曾经在一个项目里,为了省事,用 CPU 轮询方式读取高速 SPI Flash。结果 CPU 占用率飙到 90%,系统 watchdog 频繁超时复位。后来改成 DMA + 中断,CPU 占用降到 10%,问题全解决了。记住:DMA 不是锦上添花,而是雪中送炭。

1.5 DMA 传输的基本流程

虽然不同芯片的 DMA 控制器实现有差异,但基本流程大同小异。我习惯把它分成五步:

  1. 请求:外设(或软件)发出 DMA 传输请求。
  2. 仲裁:如果多个 DMA 通道同时请求,仲裁器决定优先级。
  3. 传输:DMA 控制器从源地址读取数据,写入目的地址。
  4. 计数:每传输一次,计数器减一,直到完成设定的传输次数。
  5. 完成:传输结束,DMA 控制器发出中断通知 CPU。

嗯,这里要注意:DMA 传输的单位可以是字节、半字(16位)或字(32位),具体取决于你的配置。我一般建议优先使用字传输,效率最高。

1.6 本章小结

DMA 说白了就是一个硬件数据搬运工。它的核心价值在于:让 CPU 做 CPU 该做的事,让 DMA 做 DMA 该做的事。两者各司其职,系统性能才能最大化。