一、DMA 基础概念:搬数据这件事,真的需要 CPU 亲力亲为吗?
大家好,欢迎来到这门课。我是老张,干了十来年嵌入式底层开发。
今天咱们聊点最基础的——DMA。你可能觉得这个概念太简单了,但说实话,很多项目出问题,恰恰是在“基础”上栽了跟头。
DMA 全称 Direct Memory Access,直接存储器访问。说白了,就是 CPU 把“数据搬运”的苦力活,外包给一个专门干这个的硬件小弟。
1.1 为什么需要 DMA?
你想想看,传统的数据传输是啥样的?
- CPU 轮询:CPU 不断查外设寄存器,看数据准备好了没。这期间 CPU 什么事都干不了,纯属空转。
- 中断传输:每来一个数据,CPU 就停下手头的工作,跑去执行中断服务函数。数据量大时,CPU 绝大多数时间都在“响应中断-保存现场-恢复现场”的路上。
我早期做一个小型数据记录仪项目,ADC 采样率才 100kHz,结果 CPU 被中断占用了 90% 以上的处理时间,主循环几乎跑不动。那会我就意识到——CPU 不适合干频繁的、简单的数据搬运。
DMA 的核心价值: 让 CPU 专注于计算和控制,把枯燥的数据复制、外设→内存、内存→外设这类操作,交给 DMA 控制器并行完成。
1.2 DMA 工作模式
DMA 不是什么新鲜东西。但不同模式差别很大,我把它整理成一张表,方便你对照着看:
| 模式名称 | 核心特征 | 典型场景 |
|---|---|---|
| 单次传输 | 一次请求,搬运 N 个数据,完成后停止 | 一次性数据块拷贝,比如保存一帧图像 |
| 循环传输 | 搬运完一轮,自动从头再开始 | 连续 ADC 采样,数据不断覆盖回环缓冲 |
| 乒乓传输 | 两个缓冲区交替使用:一个被 DMA 写,一个被 CPU 读 | 高频率、无丢数的连续采样,正是本课核心 |
这里我提个醒:循环传输看起来省事,但如果你只用一个缓冲区,CPU 和 DMA 同时访问同一块内存,会产生“竞争”。处理器来不及读,数据就被新的覆盖了——丢数据,坑深着呢。
我曾经踩过的坑: 一个用循环 DMA 做音频采集的项目。采样率 48kHz,看起来不高。但我没做双缓冲,主循环里处理一帧数据时,DMA 已经把后续的两帧写进去了。
结果:回放时“咔咔”爆音。后来换了乒乓 DMA,问题立刻消失。
核心教训: 只要 CPU 处理时间>单缓冲区填充时间,就必须上乒乓。
1.3 DMA 传输的基本流程
为了帮你理清整体脉络,我画了一张核心逻辑图。这张图里,你能看到三种典型 DMA 工作模式的区别:
看到没?乒乓传输的本质就是“双缓冲轮流切换”。DMA 往其中一个缓冲写数据时,CPU 去另一个缓冲取数据。两者各玩各的,互不干扰。
1.4 DMA 术语速查
刚接触 DMA 的朋友,容易被几个词绕晕。我帮你筛出最常用的:
- DMA 请求:外设发出的信号,告诉 DMA 控制器“我有数据要搬”。
- DMA 应答:DMA 控制器响应请求,开始接管总线。
- 总线仲裁:DMA 和 CPU 同时想用总线时,由仲裁器决定谁先用。通常是 DMA 优先级高于 CPU。
- 数据宽度:一次搬运多少个字节?8位、16位还是32位?这影响吞吐量。
- 传输完成中断:DMA 搬完设定数量的数据后,可以触发一个中断通知 CPU。
我建议: 在配置 DMA 时,养成先检查“外设地址”和“内存地址”是否对齐的习惯。比如源地址是 32 位对齐的,但目标地址是 8 位对齐,某些 DMA 控制器会报错或降低效率。
1.5 本章小结:你该带走什么?
回到最开始的问题:为什么要搞 DMA?说白了,就是“解放 CPU”。而乒乓 DMA,是在解放的基础上,加了“防冲突”的双保险。
- DMA 不是万能的——它只解决“数据搬运”,不处理数据。
- 单次、循环、乒乓——三者的复杂度和可靠性依次递增。
- 乒乓传输——用两个缓冲区实现了“时间和空间的错峰”,是高采样率场景的基石。
后面我会带你深挖乒乓 DMA 的配置细节、中断设计、以及如何评估系统能不能扛住目标采样率。今天先把基础夯实在。