4. DMA 请求延迟:从请求到响应的等待时间
聊完了 SPI 本身的上限,咱们得把目光聚焦到 DMA 身上了。
我个人认为,DMA 请求延迟是整个传输链路里最容易被低估的变量。很多人觉得 DMA 就是“后台搬运工”,只要配好了,它就能无延迟干活。其实不是这么回事。
4.1 什么是 DMA 请求延迟?
咱们先下一个定义。
DMA 请求延迟,指的是从外设(比如 SPI 的 RX FIFO 非空信号)发出 DMA 请求的那一刻起,到 DMA 控制器真正开始搬运第一个数据字节为止,这中间经历的总时间。
核心表达式:
DMA 请求延迟 = 请求到达 DMA 控制器的时间 + 仲裁等待时间 + 总线获取时间 + 通道启动时间
说白了,就是“喊了一嗓子,到真正动手”的间隔。这个间隔如果太大,SPI 的 FIFO 就会等得“干涸”,导致总线出现空闲周期。
4.2 延迟的四个组成部分
我在调试一个多路 SD 卡记录仪时,就吃过这个亏。当时 SPI 时钟配到了 20 MHz,按理说速度够了,但实测吞吐率只有理论值的一半。后来一查,才发现是 DMA 请求延迟把链路堵死了。
咱们把延迟拆开来看:
| 延迟阶段 | 说明 | 典型影响 |
|---|---|---|
| 1. 请求送达延迟 | 外设的中断/请求信号到达 DMA 控制器的物理延迟 | 通常很短,几 ns 到几十 ns |
| 2. 仲裁等待时间 | DMA 有多通道时,需要等当前通道传输完毕才能轮到 | 这是大头,尤其多通道共享优先级时 |
| 3. 总线获取时间 | DMA 拿到总线控制权前,CPU 或其他主机正在占用总线 | 取决于总线负载和总线仲裁算法 |
| 4. 通道启动时间 | DMA 控制器配置内部寄存器、指针,完成首个传输准备 | 部分控制器需几个时钟,部分需几十个 |
避坑提醒: 我曾经在一个项目中把 DMA 的所有通道都配成了“高优先级”,结果每个通道抢总线时互相硬等,延迟反而比低优先级策略更差。仲裁不是越快越好,你想想看,权重策略得按实际流量来设计。
4.3 延迟对 SPI 吞吐率的直接影响
你可能以为 DMA 延迟只影响第一次传输,后面就流水线了。但问题在于——单次传输之后,下一次请求的产生依然取决于 DMA 的响应及时性。
具体来说:
- SPI Master 发送一个字节后,需要从 FIFO 取下一个字节才能维持 MOSI 时钟连续。
- 如果 DMA 响应太慢,Master 取不到数据,那就只能插入“等待周期”。
- 这个等待周期就是 SPI 总线空闲周期,直接拉低有效数据率。
我举个例子你就明白了。
经验数据: 假设 SPI 时钟为 20 MHz(时钟周期 50 ns),FIFO 深度 16 字节,DMA 请求延迟为 1 μs。
FIFO 空了之后,DMA 需要 1 μs 才能补充数据,这 1 μs 就是 20 个 SPI 时钟周期全部浪费掉。
如果每 16 字节发生一次这样的延迟,吞吐率损失约 6%。要是 FIFO 深度再浅一半,损失直接翻倍。
4.4 测量 DMA 请求延迟的方法
说实话,数据手册很少直接给出 DMA 请求延迟的具体数值。我一般靠以下两种方法实测:
- GPIO 信号法:
- 在 SPI 外设产生 DMA 请求的地方(如果芯片提供了访问信号)拉高一个 GPIO。
- 在 DMA 传输开始时(比如触发中断或完成第一个字节时)拉低同一个 GPIO。
- 用逻辑分析仪测量脉冲宽度,这就是总延迟。
- 定时器捕获法:
- 使用定时器的输入捕获功能,同时捕获“请求信号”和“传输开始信号”。
- 精度高,适合微秒级以下的延迟测量。
注意: 不要只看一次测量值。DMA 延迟会随着系统负载抖动,最好采集 1000 次以上,统计最大、最小和平均延迟。
4.5 降低 DMA 请求延迟的常见手段
我根据这些年的经验,把有效的优化措施列了一下:
| 措施 | 原理/做法 | 效果评估 |
|---|---|---|
| 提高 DMA 优先级 | 给 SPI 对应的 DMA 通道配高优先级,减少仲裁等待 | 有效,但要注意影响其他外设 |
| 使用大块传输模式 | 一次触发搬运多个字节,减少请求次数 | 非常有效,但需要 FIFO 支持 |
| 锁定总线带宽 | 在部分芯片中可配置 DMA 获得总线后不被其他主机打断 | 能降低抖动,但增加 CPU 等待 |
| 分散传输 + 链式描述符 | 预先准备好多个缓存区,DMA 完成一个自动开始下一个 | 适合大量连续数据,能隐藏延迟 |
我个人习惯是优先尝试"大块传输模式" —— 效果好,改动小。但前提是你的 SPI FIFO 深度得撑得住单次搬运的数量。
4.6 本章知识图谱
下面这张图把 DMA 请求延迟的定义、组成、影响和优化串了起来。看完你就知道整个逻辑链了。
4.7 小结
这一章咱们把 DMA 请求延迟这根“隐形水管”里的四个阻塞点都理清了。记住:
- 延迟不是常数,它会随总线负载抖动。
- FIFO 深度是第一个缓冲垫,但不是万能药。
- 测量是优化的前提——别靠猜。
下次你再听到 SPI 速率跑不满,别急着调 SPI 时钟,先查查 DMA 那边是不是在“慢悠悠地起床”。