1. DMA 基础概念:为什么我们需要它?
大家好,我是这次课程的主讲。做了十几年嵌入式底层,我越来越觉得 DMA 是个被低估的模块。很多人会用,但真要说清楚它到底解决了什么问题,反而支支吾吾。今天咱们就从最基础的概念开始,把 DMA 的底裤扒干净。
1.1 什么是 DMA?
DMA,全称 Direct Memory Access,直接存储器访问。说白了,就是一块硬件,专门负责在内存和外设之间搬数据,不需要 CPU 插手。
你想想看,CPU 本来是要干大事的——跑算法、做决策、处理中断。结果呢?大部分时间都在那傻等,从外设读一个字节,存到内存,再读下一个字节……这不就是大材小用吗?
DMA 就是来解决这个问题的。它相当于一个专职的“数据搬运工”,CPU 只需要告诉它:“嘿,把 A 地址的数据搬 1024 个字节到 B 地址”,然后就可以去干别的了。搬完了,DMA 会发个中断通知 CPU。
核心要点:DMA 的本质是 CPU 的代理搬运工,它让 CPU 从繁重的数据拷贝任务中解放出来。
1.2 DMA 与 CPU 的数据搬运对比
我记得刚入行时,带我的老工程师说过一句话:“CPU 搬数据,就像让爱因斯坦去搬砖——不是不能搬,是太浪费了。” 这话糙理不糙。
咱们直接看对比表格,一目了然:
| 对比维度 | CPU 直接搬运 | DMA 搬运 |
|---|---|---|
| 搬运方式 | 逐字节/逐字读取→写入 | 硬件自动批量传输 |
| CPU 占用 | 100% 占用,无法做其他事 | 仅初始化时占用,传输中释放 |
| 传输速度 | 受限于 CPU 主频和指令周期 | 接近总线极限带宽 |
| 适用场景 | 小数据量、随机访问 | 大数据块、周期性传输 |
| 功耗 | CPU 全速运行,功耗高 | CPU 可进入低功耗模式 |
| 实时性 | 受中断和任务调度影响 | 硬件级响应,延迟可控 |
举个例子,假设你要从 UART 接收 1KB 的数据。用 CPU 轮询方式,每收到一个字节 CPU 就要进一次中断,1KB 就是 1024 次中断。每次中断保存恢复上下文、跳转、判断……光这些开销就够 CPU 喝一壶的。
用 DMA 呢?配置好源地址(UART 数据寄存器)、目的地址(内存缓冲区)、传输长度(1024),然后 DMA 控制器自己搞定一切。CPU 全程可以睡大觉,或者跑更重要的任务。
我的经验:在 STM32F4 上做过实测,同样是 1KB 数据搬运,CPU 轮询方式大约占用 80% 的 CPU 时间,而 DMA 方式只占不到 5%(主要是初始化配置那几十个周期)。差距就是这么明显。
1.3 DMA 在嵌入式系统中的角色
DMA 在嵌入式系统里到底扮演什么角色?我个人的理解是:它是系统性能的“倍增器”。
咱们来看一个典型的嵌入式系统数据流:
从这张图你能看到,DMA 处在 CPU、内存和外设的“三角关系”中心。它承担了最繁重的数据搬运工作,让 CPU 可以专注于控制逻辑和算法处理。
1.4 DMA 的典型应用场景
我这些年做过的项目里,DMA 几乎无处不在。这里列几个最常见的:
- 高速数据采集:ADC 连续采样,DMA 直接把结果搬进内存环形缓冲区,CPU 定期处理即可。我在一个电力监测项目里就是这么干的,200kHz 采样率,CPU 占用不到 10%。
- 显示刷新:LCD 或 OLED 的帧缓冲区刷新,DMA 负责把图像数据从内存搬到显示接口。没有 DMA,刷个 320x240 的屏就能把 CPU 拖死。
- 通信协议栈:UART、SPI、I2C 等接口的数据收发。尤其是高波特率 UART(比如 921600bps),不用 DMA 的话,中断频率高到吓人。
- 音频处理:I2S 音频流的 DMA 传输,配合双缓冲(ping-pong buffer)实现无间隙播放。
- 存储器操作:内存拷贝、Flash 读写、CRC 计算等,都可以交给 DMA 的专用通道。
避坑指南:我曾经在一个项目里,DMA 和 CPU 同时访问同一块内存区域,结果出现了数据不一致的问题。后来才意识到,DMA 传输时 CPU 的 cache 可能还没刷新。所以,使用 DMA 一定要考虑 cache 一致性,必要时做 cache 刷新或使用非缓存内存区域。
1.5 DMA 传输的基本流程
搞清楚了 DMA 是什么,咱们再看它具体怎么工作的。一个标准的 DMA 传输流程,大致分四步:
- 配置阶段:CPU 设置 DMA 控制器的源地址、目的地址、传输长度、传输模式(单次/循环/突发)等参数。
- 启动阶段:CPU 使能 DMA 通道,DMA 控制器进入就绪状态,等待触发信号。
- 传输阶段:外设发出 DMA 请求(或软件触发),DMA 控制器接管总线,按配置进行数据传输。每传输一个单元,内部计数器减一。
- 完成阶段:传输计数器归零,DMA 控制器产生完成中断(如果使能了中断),通知 CPU 数据已就绪。
嗯,这里要注意一点:DMA 传输期间,CPU 和 DMA 是分时共享总线的。DMA 通过“周期窃取”的方式占用总线周期,CPU 会短暂暂停。不过这个暂停时间极短,通常只有几个时钟周期,对整体性能影响微乎其微。
1.6 小结
这一章咱们把 DMA 的基础概念捋了一遍。说白了,DMA 就是让专业的人干专业的事——CPU 负责动脑子,DMA 负责出力气。搞懂了这一点,后面咱们再深入 DMA 的驱动封装和调试技巧,你就能理解为什么 HAL 层要那么设计了。