1. 课程导入

DMA,全称 Direct Memory Access,直接存储器访问。说白了,就是让外设和内存之间能直接“对话”,不需要 CPU 在中间当传话筒。

我刚开始接触嵌入式时,总觉得 DMA 是个很玄乎的东西。后来调过几块板子才明白——它就是个硬件级别的数据搬运工。你给它配好源地址、目的地址、传输长度,它自己就把活干完了。

1.1 DMA 与 CPU 的数据搬运对比

咱们先看一个最典型的场景:从 UART 接收 1KB 数据。

CPU 搬运模式:

  • CPU 每收到一个字节,就触发一次中断
  • CPU 进入中断服务函数,把数据从 UART 数据寄存器搬到内存
  • 退出中断,继续执行主程序
  • 重复 1024 次

DMA 搬运模式:

  • CPU 配置好 DMA 通道:源 = UART 数据寄存器,目的 = 内存缓冲区,长度 = 1024
  • 启动 DMA,CPU 该干嘛干嘛去
  • DMA 硬件自动搬运,每搬一个字节,硬件计数减 1
  • 计数到 0,DMA 发一个完成中断给 CPU

你想想看,这中间差了多少次中断开销?1024 次中断 vs 1 次中断。我在项目中遇到过一块板子,CPU 主频只有 72MHz,用 CPU 搬运 4KB 的 ADC 数据,CPU 占用率直接飙到 85%。换成 DMA 后,CPU 占用率降到 5% 以下。

对比项 CPU 搬运 DMA 搬运
CPU 参与度 全程参与,每个字节都要处理 仅配置和收尾,中间不参与
中断次数 每传输单元一次 整批传输一次
传输速率 受限于 CPU 指令执行速度 接近总线理论带宽
CPU 利用率 低(大量时间花在搬运上) 高(CPU 可处理其他任务)
适用场景 小数据量、随机访问 大数据量、周期性传输

核心结论:DMA 的本质是用硬件代替软件做数据搬运,释放 CPU 去做更有价值的事。这不是“优化”,而是嵌入式系统架构的必备手段。

1.2 DMA 在嵌入式系统中的角色

DMA 在嵌入式系统里到底扮演什么角色?我个人的理解是——数据管道的自动化阀门。

没有 DMA 的系统,CPU 就像个快递员,每来一个包裹都要亲自签收、登记、入库。有了 DMA,CPU 变成了仓库经理,只需要告诉系统“这批货送到几号库”,然后就可以去处理其他订单了。

具体来说,DMA 在以下几个场景中不可或缺:

  • 高速数据采集:ADC 采样率动辄几 MHz,每个样本都中断?CPU 直接挂掉。DMA 批量搬运,CPU 只做数据处理。
  • 显示刷新:LCD 显示缓冲区到屏幕的刷新,DMA 自动完成,CPU 只管画图。
  • 通信协议栈:以太网、USB、SDIO 等高速接口,数据包收发几乎都依赖 DMA。
  • 音频处理:I2S 音频流的持续传输,DMA 保证无间隙播放。
  • 存储器操作:Flash 到 RAM 的代码加载、RAM 到 RAM 的数据搬移。

个人经验:我调试过一块基于 STM32F4 的工业采集板,ADC 以 2MHz 采样,每通道 16 位数据,共 8 个通道。如果不用 DMA,CPU 每秒要处理 16M 次中断——这根本不可能。用 DMA + 双缓冲,CPU 每 1ms 才处理一次数据,稳得很。

1.3 DMA 传输的核心要素

一个完整的 DMA 传输,需要明确以下要素:

  1. 源地址:数据从哪里来(外设数据寄存器、内存地址)
  2. 目的地址:数据到哪里去(内存缓冲区、外设数据寄存器)
  3. 传输宽度:每次搬运多少位(8 位、16 位、32 位)
  4. 传输计数:总共搬运多少次
  5. 传输模式:单次、循环、乒乓等
  6. 触发源:什么事件启动一次传输(定时器、外设请求、软件触发)

嗯,这里要注意:传输宽度必须和外设寄存器宽度匹配。我曾经踩过一个坑——把 16 位 ADC 的 DMA 传输宽度配成 8 位,结果数据全乱了,高位字节和低位字节错位,折腾了两天才发现。

1.4 DMA 传输的典型流程

下面这张图展示了 DMA 一次完整传输的流程:

DMA 一次完整传输流程 1. CPU 配置 DMA 通道 2. CPU 启动 DMA 传输 3. DMA 等待触发事件 4. 触发 → DMA 搬运一次数据 5. 计数减 1,检查是否完成 计数 ≠ 0 → 回到步骤 3 计数 = 0 → 触发完成中断 6. CPU 处理完成中断 配置内容 源地址、目的地址 传输宽度、计数 触发源、模式 关键点 步骤 3-5 完全由硬件完成 CPU 只在步骤 1、2、6 参与 循环模式无步骤 6

避坑指南:我曾经在配置 DMA 循环模式时,忘记设置缓冲区大小和传输计数的匹配关系。结果缓冲区只有 256 字节,传输计数配了 1024——DMA 直接写穿了缓冲区,把后面的变量全覆盖了。板子跑起来行为诡异,查了两天才定位到。记住:DMA 没有边界检查,它只按你给的地址和计数干活,错了也照干不误。

1.5 DMA 的分类

从架构角度,DMA 主要分两类:

类型 特点 典型芯片
独立 DMA 控制器 独立于 CPU 的硬件模块,有专用总线,可同时处理多通道 STM32 DMA1/DMA2、NXP eDMA
总线主控 DMA 外设自身具备总线主控能力,可直接发起传输 USB OTG、以太网 MAC、SD/MMC 控制器

独立 DMA 控制器更灵活,可以服务多个外设。总线主控 DMA 效率更高,因为外设直接接管总线。实际项目中,两者经常配合使用。

1.6 小结

DMA 不是什么高深莫测的技术。它就是一块硬件,专门负责在内存和外设之间搬数据。用好 DMA,你的 CPU 就能从繁重的数据搬运中解放出来,去做真正的计算和控制。

记住三个核心点:

  • DMA 是硬件数据搬运工,不是 CPU 的替代品,而是 CPU 的助手
  • DMA 传输需要明确配置源、目的、宽度、计数、触发源
  • DMA 没有边界检查,配置错了后果自负