1. DMA 基础概念

1.1 DMA 工作原理

直接存储器访问(Direct Memory Access, DMA)是一种允许硬件设备直接与系统内存交换数据而无需 CPU 逐字节干预的机制。在嵌入式 Linux 系统中,DMA 是高性能 I/O 和实时数据处理的核心支撑技术。

核心思想:CPU 只需发起传输请求,DMA 控制器接管总线控制权,完成数据搬运后通过中断通知 CPU。CPU 从“搬运工”转变为“管理者”。

DMA 传输的基本流程如下:

  1. 初始化:CPU 配置 DMA 控制器的源地址、目的地址、传输长度、传输方向等参数。
  2. 启动:CPU 向 DMA 控制器发送启动命令,DMA 控制器获得总线控制权。
  3. 传输:DMA 控制器在源与目的之间直接搬运数据,每次传输后递增地址并递减计数器。
  4. 完成:当计数器归零,DMA 控制器释放总线,向 CPU 发送中断信号。
  5. 处理:CPU 在中断服务程序中处理传输完成后的数据。
DMA 传输工作流程 CPU 配置 DMA DMA 获得总线 数据搬运 传输完成中断 CPU 处理数据 CPU 在此期间 可执行其他任务

1.2 DMA 与 CPU 的协同

DMA 与 CPU 的协同工作涉及总线仲裁、缓存一致性、中断同步三个关键维度。理解这些协同机制是优化 DMA 中断处理延迟的前提。

协同维度 描述 典型问题
总线仲裁 DMA 控制器与 CPU 竞争系统总线使用权,由仲裁器决定优先级 DMA 占用总线过长导致 CPU 饥饿
缓存一致性 DMA 直接访问物理内存,CPU 缓存中的数据可能过时 脏缓存未刷新导致数据错误
中断同步 DMA 传输完成后通过中断通知 CPU,CPU 在中断上下文中处理结果 中断处理延迟影响实时性
实践要点:在 Linux 内核中,DMA 缓冲区通常使用 dma_alloc_coherent() 分配一致性内存,或使用 dma_map_single() 配合缓存刷新操作来保证一致性。

DMA 与 CPU 的协同模式可分为以下三种:

  • 轮询模式:CPU 循环检查 DMA 状态寄存器,适用于短传输或低实时性场景。
  • 中断模式:DMA 完成时触发中断,CPU 响应中断处理数据,是嵌入式 Linux 中最常用的模式。
  • 描述符链模式:DMA 自动加载下一个描述符,连续执行多个传输,仅在整链完成后触发一次中断。
DMA 与 CPU 协同架构 CPU 核心 L1/L2 缓存 MMU 系统总线(AXI / AHB) 总线仲裁器 DMA 控制器 通道 0..N 描述符引擎 系统内存(DDR) DMA 缓冲区 / 描述符表 I/O 外设 SPI / UART / ADC 中断请求 (IRQ)

1.3 DMA 传输模式

根据数据传输的组织方式和触发条件,DMA 传输模式可分为以下四种:

传输模式 触发方式 适用场景 中断频率
单次传输 软件启动 小数据块、一次性传输 每次传输完成
循环传输 硬件自动重载 音频流、连续采样 每轮循环完成
描述符链传输 链表自动加载 大数据块、分散-聚集 整链完成
请求触发传输 外设请求信号 UART RX/TX、SPI 传输 每次请求完成
延迟陷阱:单次传输模式在每次传输后都触发中断,高频中断会导致 CPU 上下文切换开销剧增。在实时系统中,应优先使用描述符链模式合并中断,或使用循环模式配合双缓冲机制。

描述符链传输是嵌入式 Linux 中最常用的高性能模式,其工作原理如下:

  1. CPU 在内存中构建描述符链表,每个描述符包含源地址、目的地址、传输长度、下一个描述符指针。
  2. DMA 控制器加载第一个描述符并执行传输。
  3. 传输完成后,DMA 自动从当前描述符中读取下一个描述符地址并加载。
  4. 当遇到描述符的“链结束”标志时,DMA 停止并触发中断。
描述符链传输模式 描述符 1 src: 0x1000 dst: 0x2000 next: → 描述符 2 描述符 2 src: 0x1100 dst: 0x2100 next: → 描述符 3 描述符 3(链尾) src: 0x1200 dst: 0x2200 next: NULL (EOL) DMA 引擎自动加载下一个描述符 无需 CPU 干预,逐链执行 链尾 → 触发中断 仅一次中断,高效
性能对比:在 1 MB 数据传输场景下,单次传输模式(每次 1 KB)会产生 1024 次中断;而描述符链模式(每条链 256 KB)仅产生 4 次中断,中断开销降低 99.6%。

选择 DMA 传输模式时,需综合考虑以下因素:

  • 数据量:小数据量(< 64 字节)适合单次传输;大数据量适合描述符链。
  • 实时性:循环传输配合双缓冲可保证固定延迟;描述符链的延迟取决于链长度。
  • 外设特性:请求触发模式适用于不定长数据的外设(如 UART)。
  • 中断负载:中断频率直接影响系统实时性,应尽量合并中断。