4. DMA基础概念:DMA控制器、DMA传输模式、DMA与CPU协同

直接存储器访问(Direct Memory Access, DMA)是嵌入式系统中实现高性能数据传输的核心机制。它允许外设与存储器之间直接交换数据,而无需CPU逐字节干预,从而大幅降低CPU负载并提升系统吞吐量。本章将深入剖析DMA控制器的硬件结构、传输模式以及DMA与CPU的协同工作模型,为后续理解DMA映射与SMMU配置奠定基础。

4.1 DMA控制器架构与核心组件

DMA控制器(DMAC)是一个独立的总线主控设备,能够发起总线事务并控制数据流。典型的DMA控制器包含以下关键模块:

组件 功能描述 硬件实现要点
通道控制器 管理多个独立DMA通道,每个通道对应一个传输上下文 通道数通常为4~32,支持优先级仲裁
源地址寄存器 存储数据源地址(外设寄存器或内存地址) 支持地址递增、递减或固定模式
目的地址寄存器 存储数据目的地址 与源地址寄存器对称设计
传输计数寄存器 记录待传输的数据单元数量 递减至0时触发传输完成中断
控制状态寄存器 配置传输模式、数据宽度、突发大小等参数 包含启动/暂停/中止控制位
总线接口单元 实现与系统总线(AHB/AXI/CHI)的协议握手 支持单次传输与突发传输
实战要点:在嵌入式Linux中,DMA控制器通常通过dmaengine框架进行抽象。驱动开发者需要关注通道分配、描述符链管理以及回调机制,而非直接操作硬件寄存器。

4.2 DMA传输模式详解

DMA控制器支持多种传输模式,以适应不同的应用场景。理解这些模式是正确配置DMA映射的前提。

4.2.1 单次传输模式

每次DMA请求只传输一个数据单元(字节、半字或字),然后释放总线。适用于低速外设或数据量较小的场景。

4.2.2 突发传输模式

一次DMA请求连续传输多个数据单元(突发长度可配置,如4、8、16次传输)。突发传输能显著提高总线利用率,但会占用总线较长时间,可能影响其他总线主控的延迟。

4.2.3 循环传输模式

传输完成后自动重置地址和计数寄存器,实现连续循环传输。常用于音频流、ADC连续采样等需要持续数据流的场景。

4.2.4 描述符链模式

通过链表组织多个传输描述符,每个描述符定义一次传输的源地址、目的地址、长度和配置。DMA控制器自动遍历链表,完成所有传输后产生中断。这是Linux内核dmaengine框架的核心传输模式。

模式对比表:
模式 总线占用 CPU干预 适用场景
单次传输 低 每次传输后需重新配置 UART、I2C等低速外设
突发传输 高 一次配置完成多次传输 高速存储、网络控制器
循环传输 持续 仅初始配置 音频、传感器数据流
描述符链 可配置 批量提交,中断少 复杂DMA操作、多缓冲区

4.3 DMA与CPU协同工作模型

DMA与CPU的协同是系统性能优化的关键。两者通过共享系统总线访问内存,必须建立清晰的同步与互斥机制。

4.3.1 协同工作流程

  1. CPU配置DMA:设置源地址、目的地址、传输长度、传输模式,并启动DMA。
  2. DMA自主传输:DMA控制器接管总线控制权,按配置完成数据传输。CPU可继续执行其他任务。
  3. 传输完成通知:DMA通过中断或轮询标志通知CPU传输结束。
  4. CPU处理数据:CPU检查数据一致性(Cache刷新/无效化),处理传输结果。

4.3.2 缓存一致性问题

在带Cache的系统中,DMA直接访问物理内存,而CPU可能通过Cache访问同一内存区域。这会导致数据不一致:

  • DMA写入内存,CPU读取:CPU Cache中可能包含旧数据,需执行Cache无效化操作。
  • CPU写入内存,DMA读取:CPU写入的数据可能仍在Cache中未写回内存,需执行Cache写回操作。
常见错误:驱动开发中遗漏Cache一致性操作是导致DMA数据传输错误的头号原因。在Linux内核中,应使用dma_map_single()/dma_unmap_single()等API自动处理Cache维护,而非手动操作。

4.3.3 同步机制

DMA与CPU的同步通常通过以下方式实现:

同步方式 延迟 CPU开销 适用场景
中断 中等(中断响应延迟) 低(仅处理中断时) 大多数DMA传输
轮询状态寄存器 低(立即检测) 高(持续占用CPU) 短时、高实时性传输
DMA完成回调 取决于调度 低(内核上下文处理) Linux dmaengine框架

4.4 DMA传输流程SVG架构图

下图展示了从CPU配置DMA到传输完成的完整流程,以及DMA与CPU、内存、外设之间的数据通路:

DMA传输流程架构图 DMA传输流程与协同架构 CPU 配置DMA / 处理数据 DMA控制器 通道 / 描述符 / 状态 系统内存 数据缓冲区 外设 UART / SPI / 网卡 配置通道/描述符 DMA读/写数据 DMA请求/应答 Cache一致性操作(写回/无效化) 传输完成中断 关键协同点: ① CPU配置DMA后立即返回,实现计算与传输并行; ② DMA传输期间CPU可执行其他任务,提升系统吞吐量; ③ 传输完成后通过中断同步,CPU需处理Cache一致性。

4.5 DMA传输模式选择策略

在实际嵌入式系统中,选择合适的DMA传输模式需要综合考虑以下因素:

  • 数据量大小:小数据量(< 64字节)适合单次传输,大数据量(> 1KB)适合突发传输。
  • 实时性要求:高实时性场景应避免长时间突发传输阻塞总线。
  • 外设特性:FIFO深度小的外设需使用单次传输防止溢出;支持流控制的外设可配合突发传输。
  • 系统负载:多DMA通道并发时,需合理分配优先级和带宽。
Linux内核实践:在设备树中配置DMA时,通常通过dma-burst-size和dma-maxburst属性指定突发长度。驱动中调用dmaengine_slave_config()设置src_addr_width、dst_addr_width和src_maxburst等参数。

4.6 本章小结