案例定位
这页用两类很典型、但经常被低估的场景来补齐 DMA 专题的第三个角:
- ADC 周期采样:强调采样时刻、触发源、周期窗口与模拟前端延迟
- UART + circular DMA + IDLE:强调持续输入流、环形缓存、事件驱动回收与消费速度失衡
一、为什么这一类案例很重要
如果:
- 音频 DMA 案例最适合讲 周期流节拍
- 网卡 DMA 案例最适合讲 高吞吐 ring 并发推进
那 ADC / UART 这类案例最适合讲的是:
- 持续采集不是只会“收数据”,而是要精确控制“何时采、采到哪、来不来得及处理”
- DMA 不只是搬运通道,还是系统实时性边界的一部分
二、这类驱动最该抓的,不是带宽,而是时机
ADC 场景:采对时刻,比采得快更重要
以电流采样这类 ADC 驱动为例,真正关键的问题不是“ADC 开没开”,而是:
- 触发源是谁
- 采样窗口在哪里
- PWM、死区、预驱、放大器、ADC 本身的延迟怎么算
- 采样时刻是否已经滑到噪声区或尖峰区
也就是说,ADC + DMA 场景最值钱的洞察是:
DMA 负责把样本搬回来,但“什么时候采”才是决定数据质量的第一变量。
UART 场景:收得回来,不代表处理得过来
UART + circular DMA + IDLE 这类场景又是另一种问题:
- 数据并不总是按固定 period 到达
- 用户态 / 任务层处理速度可能跟不上
- 缓冲区可能线性推进,也可能发生回卷
- 半传输、全传输、IDLE 事件可能交错到来
所以 UART 这类持续输入流最该思考的是:
DMA 只是把数据送进环形缓冲区,系统真正的成败在于消费侧是否能及时、正确、低抖动地把它接走。
三、ADC DMA 驱动怎么看
1. 先看触发链,而不是先看 buffer
一个成熟 ADC 采样链路通常要先回答:
- 定时器哪个事件触发 ADC
- ADC 是规则通道还是注入通道
- 是否双 ADC 同步采样
- DMA 在转换完成后如何搬结果
如果你一开始只盯
DMA buffer,那通常会错过真正决定质量的 trigger path。2. 采样窗口才是 ADC DMA 的灵魂
像相电流检测这类场景,采样窗口通常受这些东西共同限制:
- PWM 占空比
- 死区时间
- MOS 开关延迟
- 放大器与滤波器延迟
- ADC 本身转换时间
所以这类驱动的本质不是“配个 DMA 通道”,而是:
在真实硬件延迟预算下,给采样动作找到一块还算干净的时间窗口。
3. 规则组 / 注入组 / 双 ADC 模式,不是配置项堆砌
它们背后对应的是不同的系统目标:
- 规则组:更像常规连续采样数据面
- 注入组:更像在关键时刻插队,优先拿到高价值样本
- 双 ADC 同步:更像为了保证多路信号在同一时刻被看到
也就是说,别把这些选项当菜单。它们是在回答:
- 你要的到底是吞吐、确定性,还是同步性?
四、UART circular DMA 驱动怎么看
1. 它本质上是“持续输入流 + 环形消费”问题
UART DMA 接收不是“来一帧处理一帧”那么简单。
在 circular DMA 模式下,真正要治理的是:
- DMA 写指针持续往前推
- CPU / 线程从旧位置开始消费
- 如果消费慢,缓冲区会回卷并覆盖旧数据
2. IDLE / HT / TC 不是三种零散中断,而是三种观察点
- HT:说明前半段可处理
- TC:说明整块写满了一轮
- IDLE:说明这一波输入暂时停了,适合把尾巴收掉
这三者一起用时,本质是在回答:
我现在从哪儿到哪儿这段数据,已经足够稳定,可以交给 CPU 处理?
3. old_pos -> pos 模型为什么重要
持续输入流里一个非常值钱的处理框架就是:
- 记录上一次消费位置
old_pos
- 当前 DMA 到达位置记为
pos
- 如果
pos > old_pos,处理线性区间
- 如果
pos < old_pos,说明发生回卷,要拆成两段处理
这其实就是 ring buffer 消费协议在 MCU 外设接收场景下的缩微版。
五、把这两个案例放在一起看,会看见什么
共同点
ADC 和 UART 这类持续采集 DMA 驱动,都有三个共性:
- 数据是持续到来的,不是一次性事务
- 软件消费速度不一定和硬件生产速度一致
- 真正难点不在“开 DMA”,而在“定义稳定的交接窗口”
差异点
维度 | ADC 周期采样 | UART circular DMA |
核心矛盾 | 采样时刻是否准确 | 消费是否跟得上生产 |
关键边界 | trigger / window / latency | write pos / old pos / overflow |
主要风险 | 采到尖峰、相位错位、样本失真 | 缓冲区覆盖、帧边界错判、处理抖动 |
更像什么 | 时序精度问题 | 持续流消费问题 |
六、在主线里,这个案例对应哪些章节
这页最适合和这些章节一起看:
如果你把三类案例连起来看:
- 这页的 ADC / UART 持续采集
你会更容易真正建立对 DMA 世界的立体感。
七、读这类源码时该追的问题
ADC 类
- 触发源是谁?Timer 哪个事件?
- 规则组还是注入组?为什么?
- 采样窗口是否考虑了死区与模拟前端延迟?
- DMA 搬回来后,结果由谁消费、何时消费?
UART 类
- DMA 是 normal 还是 circular?为什么?
IDLE / HT / TC各自承担什么观察职责?
- 消费位置怎么维护?回卷怎么处理?
- 若处理跟不上,系统是丢数据、阻塞还是扩大缓冲?
八、真正要带走的判断
持续采集类 DMA 驱动的核心,不是“把数据搬进内存”,而是 找到稳定的采样 / 交接窗口,并保证消费速度不会把系统拖进覆盖与抖动地狱。
这句话一旦立住,你再看 ADC、UART、采集卡,思路就不会散。





