2. DMA 基础原理

DMA(Direct Memory Access,直接存储器访问)是嵌入式系统中实现高速数据传输的核心机制。它允许外设与存储器之间直接交换数据,无需 CPU 逐字节干预,从而大幅降低 CPU 负载并提升系统吞吐量。在网关设备中,DMA 被广泛用于网络数据包收发、存储设备读写以及高速串行接口(如 SPI、I2S)的数据搬运。理解 DMA 控制器的工作原理、传输模式以及描述符环结构,是诊断 DMA 传输超时与 Cache 一致性问题的前提。

2.1 DMA 控制器工作原理

DMA 控制器本质上是一个专用的硬件状态机,负责在源地址与目的地址之间搬运数据。其核心工作流程如下:

  1. CPU 配置:CPU 通过寄存器设置 DMA 通道的源地址、目的地址、传输长度、传输模式以及触发源(如外设请求信号)。
  2. 外设请求:当外设(如以太网 MAC、USB 控制器)准备好接收或发送数据时,向 DMA 控制器发送硬件请求信号。
  3. 总线仲裁:DMA 控制器向系统总线仲裁器申请总线控制权。获得授权后,DMA 成为总线主设备。
  4. 数据搬运:DMA 控制器在源地址读取数据,写入目的地址,同时更新内部地址指针和计数器。
  5. 传输完成:当计数器归零或收到终止信号时,DMA 控制器向 CPU 发送中断,或更新状态寄存器供 CPU 轮询。
关键概念: DMA 传输的粒度可以是字节、半字(16 位)或字(32 位)。地址对齐要求因硬件而异,通常源地址和目的地址必须与传输粒度对齐,否则可能触发总线错误或性能下降。
DMA 控制器工作原理流程图 CPU 配置 DMA 通道 外设发送请求信号 总线仲裁 & 获得控制权 数据搬运(源→目的) 传输完成 → 触发中断 CPU 配置源/目的地址、 传输长度、触发源等参数 到 DMA 通道寄存器 DMA 成为总线主设备, 占用系统总线进行传输

2.2 DMA 传输模式

根据应用场景和硬件能力,DMA 控制器支持多种传输模式。选择合适的模式对系统性能和实时性有显著影响。下表对比了三种最常见的 DMA 传输模式:

传输模式 描述 典型应用 总线占用 传输效率
单次传输 每次 DMA 请求只传输一个数据单元(字节/半字/字),然后释放总线 低速外设(UART、I2C) 低 低
突发传输 一次 DMA 请求连续传输多个数据单元(突发长度可配置,如 4/8/16 字) 高速外设(以太网、USB) 高(但总次数少) 高
链式传输 通过描述符链表将多个 DMA 传输任务串联,硬件自动加载下一个描述符 大数据块搬运、网络数据包收发 中等(连续传输) 极高
常见陷阱: 突发传输虽然效率高,但过长的突发长度可能导致 CPU 或其他高优先级外设长时间无法访问总线,引发延迟抖动。在网关设备中,建议将突发长度控制在 8~16 字以内,并配合优先级设置使用。

2.2.1 单次传输模式

单次传输是最基本的 DMA 模式。每次外设请求,DMA 控制器只搬运一个数据单元,然后释放总线控制权。该模式实现简单,对总线干扰小,但传输效率较低,因为每次传输都需要重新进行总线仲裁。适用于波特率较低的串行接口。

2.2.2 突发传输模式

突发传输模式下,DMA 控制器在一次总线授权后连续搬运多个数据单元。突发长度(Burst Length)通常可配置为 4、8、16 或 32 字。突发传输能显著减少总线仲裁次数,提高有效带宽。但需要注意,突发传输会长时间占用总线,可能影响其他总线主设备的响应时间。

2.2.3 链式传输模式

链式传输是 DMA 的高级模式,也是网关驱动中最常用的模式。它通过一个描述符链表(Descriptor Chain)来管理多个传输任务。每个描述符包含源地址、目的地址、传输长度、控制标志以及指向下一个描述符的指针。DMA 控制器完成当前描述符后,自动加载下一个描述符并继续传输,无需 CPU 干预。

链式传输:描述符链表结构 描述符 1 源地址: 0x8000_0000 目的地址: 0xA000_0000 长度: 1024 字节 Next: → 描述符 2 控制: 中断使能 描述符 2 源地址: 0x8000_0400 目的地址: 0xA000_0400 长度: 512 字节 Next: → 描述符 3 控制: 无中断 描述符 3 源地址: 0x8000_0600 目的地址: 0xA000_0600 长度: 2048 字节 Next: NULL (结束) 控制: 中断使能 链式传输特点:DMA 硬件自动加载下一个描述符,CPU 只需初始化链表首地址。 当描述符 3 完成后触发中断,CPU 处理整个链表的完成事件,无需逐段干预。

2.3 DMA 描述符环

描述符环(Descriptor Ring)是链式传输的一种特殊实现,广泛应用于网络控制器(如 Intel I210、DesignWare EMAC)和存储控制器中。与简单的链表不同,描述符环是一个循环缓冲区,最后一个描述符的 Next 指针指向第一个描述符,形成闭环。

描述符环的核心优势在于:

  • 固定内存开销:环的大小在初始化时确定,不会动态增长,适合实时系统。
  • 硬件自动回绕:DMA 控制器在到达环尾时自动跳转到环首,无需软件干预。
  • 生产者-消费者模型:CPU(软件)负责填充待发送的描述符或回收已接收的描述符;DMA 硬件负责消费描述符并执行传输。
驱动开发要点: 描述符环通常使用两个指针进行管理——硬件头指针(Head Pointer)和软件尾指针(Tail Pointer)。硬件从 Head 指向的描述符开始执行,软件通过更新 Tail 来通知硬件有新的描述符可用。这种机制有效避免了竞争条件。
DMA 描述符环结构(循环缓冲区) 描述符 0 (Head →) 描述符 1 (已提交) 描述符 2 (已提交) 描述符 3 (Tail →) 描述符 4 (空闲) 描述符 5 (空闲) Head 指针:硬件当前正在处理的描述符位置;Tail 指针:软件最后提交的描述符位置。 硬件从 Head 开始执行,遇到 Tail 时停止;软件通过更新 Tail 来通知硬件有新的工作项。

2.4 描述符字段详解

一个典型的 DMA 描述符包含以下关键字段。不同厂商的硬件可能在位宽和布局上有所差异,但核心语义一致:

字段 位宽 描述
源地址 32/64 位 数据源的内存地址或外设地址(如 FIFO 地址)
目的地址 32/64 位 数据目标的内存地址或外设地址
传输长度 16/32 位 本次传输的字节数或字数。通常为 0 表示无效描述符
控制标志 16/32 位 包含中断使能、传输方向、突发类型、地址递增模式等控制位
状态标志 16/32 位 由硬件写入,指示传输完成、错误类型(如总线错误、超时)
Next 指针 32/64 位 指向下一个描述符的物理地址。在环结构中,最后一个指向第一个
Cache 一致性隐患: 描述符通常位于主存中,而 DMA 控制器直接访问主存。如果 CPU 修改了描述符但 Cache 未写回,或者 DMA 写入了描述符状态但 CPU 读取了过期的 Cache 行,就会导致描述符数据不一致。这是后续章节将要重点解决的 Cache 一致性问题。

2.5 本章小结

DMA 控制器通过硬件状态机实现高效的数据搬运,其工作原理涉及 CPU 配置、外设请求、总线仲裁和数据搬运四个阶段。三种传输模式——单次、突发和链式——分别适用于不同速率和实时性要求的外设。描述符环作为链式传输的循环实现,是网关驱动中管理网络数据包的核心数据结构。理解描述符的字段含义和环的管理机制,是后续分析 DMA 传输超时和 Cache 一致性故障的基础。