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 传输信号流与总线交互示意 CPU 配置 / 中断处理 DMA 控制器 源地址 / 目的地址 长度 / 方向 / 计数 内存 缓冲区 / 描述符 外设 网卡 / UART / ADC FIFO / 数据寄存器 配置寄存器 写内存 读内存 DREQ 请求 DACK 应答 传输完成中断 系统总线 / 总线仲裁:地址总线 + 数据总线 + 控制总线

二、DMA传输模式:不同场景选不同模式

DMA 控制器通常支持多种传输模式,不同模式决定了数据搬运的粒度、CPU 的参与程度以及总线占用方式。常见模式包括:

  • 单次传输(Single Transfer):每次 DREQ 只搬运一个数据单元,适合低速外设或对实时性要求高的场景。
  • 块传输(Block Transfer):一次请求连续搬运一整块数据,直到计数器归零。吞吐高,但会长时间占用总线。
  • 突发传输(Burst Transfer):以突发方式占用总线,连续搬运多个数据单元后释放总线,兼顾吞吐与总线公平性。
  • 循环传输(Circular / Ring):传输完成后自动回到起始地址,适合音频、ADC 采样等连续数据流场景。
  • 分散-聚集(Scatter-Gather):通过描述符链表把多个不连续的内存块串联起来,一次配置完成多段传输,适合网络包、视频帧等非连续缓冲区。

在吞吐测试中,块传输和突发传输最常用,因为它们能显著减少 CPU 中断次数和总线仲裁开销。但要注意,块传输过大可能导致其他外设长时间得不到总线,反而拉低系统整体吞吐。

三、DMA与CPU交互机制:并行、竞争与同步

DMA 与 CPU 的关系可以概括为“并行工作、共享总线、通过中断同步”。CPU 负责配置 DMA 和响应中断,DMA 负责搬运数据,两者在大部分时间里是并行的。但它们共享同一套总线,因此存在总线竞争。

常见的交互机制有三种:

  1. 停止 CPU 访问总线(Halt / Blocking):DMA 传输期间 CPU 暂停访问总线。实现简单,但 CPU 性能损失大,不适合高吞吐场景。
  2. 周期窃取(Cycle Stealing):DMA 每次只占用一个总线周期,然后归还给 CPU。CPU 几乎不受影响,但 DMA 传输速率受限。
  3. 透明传输(Transparent):DMA 只在 CPU 不使用总线时搬运数据。对 CPU 影响最小,但 DMA 吞吐最低。

在吞吐测试中,通常需要在“DMA 吞吐”和“CPU 可用性”之间做权衡。如果测试目标是极限吞吐,可以允许 DMA 长时间占用总线;如果测试目标是系统整体响应,则应采用周期窃取或突发传输。

提示:很多 SoC 的 DMA 控制器支持多通道和优先级配置。高优先级通道可以抢占低优先级通道的总线使用权,这在多外设并发吞吐测试中非常关键。

四、关键术语解析与常见误区

理解 DMA 术语是排查吞吐问题的第一步。下表整理了吞吐测试中最常出现的术语及其实际含义:

术语 含义 吞吐测试中的关注点
DREQ / DACK 外设请求 / DMA 应答信号 握手是否及时,是否出现请求丢失
传输描述符 描述源、目的、长度、下一段地址的结构 描述符是否对齐,是否频繁重载
突发长度 一次总线占用连续搬运的数据量 过大影响总线公平,过小增加开销
FIFO 深度 外设或 DMA 内部缓冲深度 深度不足会导致溢出或欠载
中断合并 多个传输完成事件合并为一次中断 减少 CPU 中断次数,提升吞吐
地址对齐 源/目的地址是否按总线宽度对齐 非对齐访问会降低有效带宽

一个常见误区是“DMA 一定比 CPU 搬运快”。实际上,如果 DMA 配置不当,例如突发长度过小、描述符频繁重载、地址未对齐,DMA 的有效吞吐可能还不如优化后的 CPU 搬运。另一个误区是“DMA 传输不需要 CPU 参与”。虽然数据搬运不需要 CPU 逐字节介入,但配置、中断处理和错误恢复仍然依赖 CPU。如果中断过于频繁,CPU 会被中断上下文拖垮,反而成为吞吐瓶颈。

注意:在吞吐测试中,如果发现 DMA 传输完成中断频率过高,应优先检查是否启用了中断合并或传输完成阈值。很多 DMA 控制器支持“传输 N 个数据后才产生一次中断”,合理设置可以显著降低 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 基础概念不是理论,而是直接影响吞吐测试结果的关键参数。