2、DMA基础概念:DMA工作原理、传输模式、与CPU交互机制及关键术语解析
在吞吐测试场景中,CPU 往往不是瓶颈,真正限制数据搬运效率的,是数据从外设到内存、或从内存到外设的路径。DMA(Direct Memory Access,直接存储器访问)正是为解决这一问题而存在的硬件机制:它允许外设与内存之间直接搬运数据,而不需要 CPU 逐字节参与。理解 DMA 的工作原理、传输模式以及它与 CPU 的交互方式,是后续做吞吐优化的前提。
一、DMA工作原理:把“搬数据”从CPU手里接过来
在没有 DMA 的系统中,CPU 需要执行“读—写”循环:从外设寄存器读取一个数据,再写入内存缓冲区,反复进行。这种方式下,CPU 的时间被大量消耗在数据搬运上,真正用于协议解析、业务处理的时间被压缩。DMA 控制器(DMAC)的出现,相当于在内存和外设之间增加了一条“专用搬运通道”。
一次典型的 DMA 传输包含四个关键要素:源地址、目的地址、传输长度和触发事件。CPU 只需完成初始化配置,把源地址、目的地址、传输长度、传输方向等参数写入 DMA 控制器寄存器,然后启动传输。之后,DMA 控制器会向外设发起请求、获得数据、写入内存,并在传输完成后产生中断通知 CPU。整个过程 CPU 不参与逐字节搬运,只在开始和结束时介入。
从信号流角度看,DMA 传输依赖三条关键信号:外设发出的 DMA 请求(DREQ)、DMA 控制器返回的应答(DACK),以及总线仲裁信号。当外设需要传输数据时,它拉高 DREQ;DMA 控制器向总线仲裁器申请总线控制权;获得授权后,DMA 控制器控制地址总线和数据总线,完成一次数据读写;随后释放总线,等待下一次请求。
二、DMA传输模式:不同场景选不同模式
DMA 控制器通常支持多种传输模式,不同模式决定了数据搬运的粒度、CPU 的参与程度以及总线占用方式。常见模式包括:
- 单次传输(Single Transfer):每次 DREQ 只搬运一个数据单元,适合低速外设或对实时性要求高的场景。
- 块传输(Block Transfer):一次请求连续搬运一整块数据,直到计数器归零。吞吐高,但会长时间占用总线。
- 突发传输(Burst Transfer):以突发方式占用总线,连续搬运多个数据单元后释放总线,兼顾吞吐与总线公平性。
- 循环传输(Circular / Ring):传输完成后自动回到起始地址,适合音频、ADC 采样等连续数据流场景。
- 分散-聚集(Scatter-Gather):通过描述符链表把多个不连续的内存块串联起来,一次配置完成多段传输,适合网络包、视频帧等非连续缓冲区。
在吞吐测试中,块传输和突发传输最常用,因为它们能显著减少 CPU 中断次数和总线仲裁开销。但要注意,块传输过大可能导致其他外设长时间得不到总线,反而拉低系统整体吞吐。
三、DMA与CPU交互机制:并行、竞争与同步
DMA 与 CPU 的关系可以概括为“并行工作、共享总线、通过中断同步”。CPU 负责配置 DMA 和响应中断,DMA 负责搬运数据,两者在大部分时间里是并行的。但它们共享同一套总线,因此存在总线竞争。
常见的交互机制有三种:
- 停止 CPU 访问总线(Halt / Blocking):DMA 传输期间 CPU 暂停访问总线。实现简单,但 CPU 性能损失大,不适合高吞吐场景。
- 周期窃取(Cycle Stealing):DMA 每次只占用一个总线周期,然后归还给 CPU。CPU 几乎不受影响,但 DMA 传输速率受限。
- 透明传输(Transparent):DMA 只在 CPU 不使用总线时搬运数据。对 CPU 影响最小,但 DMA 吞吐最低。
在吞吐测试中,通常需要在“DMA 吞吐”和“CPU 可用性”之间做权衡。如果测试目标是极限吞吐,可以允许 DMA 长时间占用总线;如果测试目标是系统整体响应,则应采用周期窃取或突发传输。
四、关键术语解析与常见误区
理解 DMA 术语是排查吞吐问题的第一步。下表整理了吞吐测试中最常出现的术语及其实际含义:
| 术语 | 含义 | 吞吐测试中的关注点 |
|---|---|---|
| DREQ / DACK | 外设请求 / DMA 应答信号 | 握手是否及时,是否出现请求丢失 |
| 传输描述符 | 描述源、目的、长度、下一段地址的结构 | 描述符是否对齐,是否频繁重载 |
| 突发长度 | 一次总线占用连续搬运的数据量 | 过大影响总线公平,过小增加开销 |
| FIFO 深度 | 外设或 DMA 内部缓冲深度 | 深度不足会导致溢出或欠载 |
| 中断合并 | 多个传输完成事件合并为一次中断 | 减少 CPU 中断次数,提升吞吐 |
| 地址对齐 | 源/目的地址是否按总线宽度对齐 | 非对齐访问会降低有效带宽 |
一个常见误区是“DMA 一定比 CPU 搬运快”。实际上,如果 DMA 配置不当,例如突发长度过小、描述符频繁重载、地址未对齐,DMA 的有效吞吐可能还不如优化后的 CPU 搬运。另一个误区是“DMA 传输不需要 CPU 参与”。虽然数据搬运不需要 CPU 逐字节介入,但配置、中断处理和错误恢复仍然依赖 CPU。如果中断过于频繁,CPU 会被中断上下文拖垮,反而成为吞吐瓶颈。
五、一个典型的吞吐测试场景
假设我们在一颗 SoC 上测试网卡到内存的接收吞吐。网卡通过 DMA 把数据包写入内存环形缓冲区,CPU 负责处理描述符和协议栈。初始配置如下:
DMA 通道:CH0
传输方向:外设 → 内存
传输模式:分散-聚集(Scatter-Gather)
描述符数量:256
突发长度:16 拍
中断合并阈值:8 个描述符
缓冲区对齐:64 字节
测试中发现吞吐只有 400 Mbps,远低于网卡标称的 1 Gbps。排查后发现两个问题:一是描述符数量太少,导致 DMA 频繁等待 CPU 回收描述符;二是中断合并阈值设置为 1,每个描述符完成都产生中断,CPU 被中断淹没。把描述符增加到 1024、中断合并阈值调整为 32 后,吞吐提升到 920 Mbps。这个案例说明,DMA 基础概念不是理论,而是直接影响吞吐测试结果的关键参数。