DMA 基础概念:为什么你的 CPU 不该干搬运的活
做嵌入式开发这些年,我见过太多工程师把 CPU 当苦力使。数据从外设搬到内存,又从内存搬到外设,CPU 忙得团团转,真正该做的算法运算反而没时间搞。说白了,这就是没用好 DMA。
DMA 全称 Direct Memory Access,直接存储器访问。名字挺绕口,但本质很简单——它是个专门干数据搬运的硬件模块。CPU 把搬运任务交代给它,就能腾出手干正事了。
核心观点:DMA 不是魔法,它只是把 CPU 从「数据搬运工」的角色解放出来,让 CPU 回归「计算决策者」的本职。
1.1 什么是 DMA?一个硬件搬运工
DMA 是芯片内部的一个独立硬件模块。它有自己的总线接口,能直接访问存储器和外设寄存器。你给它配好源地址、目标地址、传输长度,它就能自己把数据搬完,搬完了再通知 CPU 一声。
我习惯把 DMA 比作工厂里的自动叉车。CPU 是厂长,负责下指令、做决策。如果没有叉车,厂长就得亲自搬货,效率可想而知。有了 DMA 这个自动叉车,厂长只要说「把 A 仓库的货搬到 B 车间」,叉车自己就干完了。
DMA 的典型工作流程:
- CPU 配置 DMA 控制器:设置源地址、目标地址、传输长度、传输模式
- DMA 启动传输:CPU 写一个启动位,DMA 开始干活
- DMA 搬运数据:DMA 通过总线读取源数据,写入目标地址,不需要 CPU 参与
- 传输完成中断:DMA 发中断通知 CPU「活干完了」
我的经验:刚开始用 DMA 时,我总忍不住在启动 DMA 后轮询它的完成标志。后来发现这完全多余——DMA 自己会处理好一切,你只管等中断就行。轮询反而浪费了 DMA 的优势。
1.2 DMA 与 CPU 数据搬运:天壤之别
很多人觉得「CPU 也能搬数据啊,为什么非要用 DMA?」。嗯,这里面的差别大了去了。我整理了一个对比表,你看完就明白了。
| 对比维度 | CPU 搬运 | DMA 搬运 |
|---|---|---|
| 执行方式 | 逐条指令执行,每搬一个字节都要取指、译码、执行 | 硬件自动完成,一个时钟周期搬一个数据单元 |
| CPU 占用 | 100% 占用 CPU,CPU 无法做其他事 | 仅配置和完成中断时占用 CPU,传输过程 CPU 可做其他事 |
| 传输速度 | 受限于指令执行速度,通常几十 MB/s | 接近总线带宽,可达几百 MB/s 甚至更高 |
| 功耗 | CPU 全速运行,功耗高 | DMA 模块功耗远低于 CPU,适合低功耗场景 |
| 实时性 | 受中断和任务调度影响,延迟不确定 | 硬件级传输,延迟可预测 |
| 适用场景 | 小数据量、非频繁传输 | 大数据块、周期性传输、高速外设 |
你想想看,如果 CPU 每接收一个字节都要跑一趟中断服务程序,那系统还能干别的吗?我曾经在一个音频项目里,用 CPU 轮询方式读取 I2S 数据,结果 CPU 负载飙到 90% 以上,系统几乎卡死。换成 DMA 后,CPU 负载直接降到 15%,音频处理算法也能流畅跑了。
避坑指南:我曾经在一个项目中,为了省事直接用 CPU 搬运 SPI Flash 的数据。结果发现 CPU 被完全占死,按键响应延迟超过 200ms。后来改成 DMA 传输,CPU 负载从 85% 降到 12%,问题迎刃而解。记住:凡是涉及大数据块传输的场景,优先考虑 DMA。
1.3 DMA 在嵌入式系统中的角色
DMA 在嵌入式系统里扮演什么角色?我总结了三个核心定位:
- 性能加速器:让 CPU 从数据搬运中解脱,专注于计算和控制
- 实时性保障:硬件级传输保证确定性的延迟,适合音频、视频等实时场景
- 功耗优化器:DMA 模块功耗远低于 CPU,在低功耗 IoT 设备中至关重要
具体到实际应用,DMA 最常见的场景包括:
- 外设数据采集:ADC 采样数据通过 DMA 直接存入内存缓冲区
- 显示刷新:LCD 显存数据通过 DMA 传输到显示控制器
- 通信协议:UART、SPI、I2C 等接口的数据收发
- 存储器操作:内存拷贝、Flash 读写、SRAM 间数据传输
- 多媒体处理:音频播放、视频采集的数据流传输
我的建议:新手入门 DMA,先从「外设到内存」的单次传输开始练手。比如用 DMA 把 ADC 的采样结果自动存到一个数组里。这个模式最简单,也最容易验证效果。等熟悉了再尝试「内存到内存」和「循环模式」。
1.4 DMA 传输的核心流程
为了让你更直观地理解 DMA 的工作机制,我画了一张流程图。这张图展示了从 CPU 配置到传输完成的完整链路。
这张图把 DMA 传输拆成了五个关键步骤。你仔细看第三步到第四步之间——CPU 写完启动位后,就可以去干别的事了。DMA 自己完成总线读写、地址递增、计数递减这些琐碎工作。这就是 DMA 的精髓所在。
1.5 什么时候该用 DMA?
不是所有场景都需要 DMA。我总结了一个简单的判断标准:
- 数据量 > 100 字节:用 DMA 收益明显
- 传输频率 > 1 kHz:用 DMA 避免频繁中断
- CPU 负载 > 30%:考虑用 DMA 分担
- 实时性要求高:DMA 的确定性延迟更可靠
反过来,如果只是偶尔传几个字节,或者传输频率很低,用 CPU 直接操作反而更简单。没必要为了用 DMA 而用 DMA。
一句话总结:DMA 是嵌入式系统性能调优的第一把钥匙。用好它,你的 CPU 就能从「搬运工」变成「指挥官」。接下来的章节,我会带你深入 DMA 的配置细节和实战技巧。