3. DMA控制器硬件原理

DMA(Direct Memory Access)控制器是系统中负责在内存与外设之间、或内存与内存之间直接搬运数据的硬件引擎。理解其内部组成与传输流程,是驱动开发者正确配置和使用DMA引擎的基础。

3.1 DMA控制器内部组成

一个典型的DMA控制器由以下核心模块构成:

核心模块一览:
  • 通道(Channel):独立的DMA传输上下文,每个通道可独立配置源地址、目的地址、传输宽度和传输计数。
  • 请求线(Request Line):外设向DMA控制器发起传输请求的硬件信号线,通常与硬件握手信号(DREQ/DACK)关联。
  • 地址发生器(Address Generator):根据配置的地址模式(递增、递减、固定)自动生成源和目的地址,无需CPU干预。
  • 控制/状态寄存器组:存放通道配置、传输状态、中断标志等控制信息。
  • 仲裁器(Arbiter):当多个通道同时请求时,按优先级策略分配总线使用权。

下图展示了DMA控制器的内部结构及各模块之间的连接关系:

DMA控制器内部组成结构图 DMA控制器内部组成结构 系统总线接口 仲裁器 (Arbiter) DMA 通道组 通道 0 源地址 / 目的地址 传输计数 / 控制 通道 1 源地址 / 目的地址 传输计数 / 控制 通道 2 源地址 / 目的地址 传输计数 / 控制 地址发生器 (Address Generator) 请求线 (Request Lines) DREQ0 / DACK0 DREQ1 / DACK1 DREQ2 / DACK2 控制 / 状态寄存器组 每个通道独立拥有地址寄存器、计数器和控制位,请求线将外设与特定通道绑定

3.2 通道(Channel)

通道是DMA控制器的基本执行单元。每个通道包含一组寄存器,用于描述一次DMA传输的全部参数:

寄存器 宽度 描述
源地址寄存器 (SAR) 32/64位 数据源起始地址,支持递增、递减或固定模式
目的地址寄存器 (DAR) 32/64位 数据目的起始地址,支持递增、递减或固定模式
传输计数寄存器 (TCR) 16/32位 待传输的数据单元数量,每完成一次传输递减
控制寄存器 (CR) 32位 配置传输方向、宽度、突发大小、中断使能等
状态寄存器 (SR) 32位 指示通道是否忙、传输完成、错误等状态
通道数量与系统设计: 嵌入式SoC中DMA通道数通常为4~32个。驱动开发时需注意通道的独占性——同一通道不能被两个外设同时使用,否则会导致地址和计数冲突。

3.3 请求线(Request Line)

请求线是外设与DMA控制器之间的硬件握手信号线。典型的请求线包括:

  • DREQ (DMA Request):外设向DMA控制器发出的传输请求信号,表示外设已准备好发送或接收数据。
  • DACK (DMA Acknowledge):DMA控制器向外设发出的应答信号,表示当前总线周期已被分配给该外设。
  • EOP (End of Process):可选信号,用于指示传输结束或外部终止。

请求线的触发方式分为电平触发和边沿触发两种:

触发方式 特点 适用场景
电平触发 DREQ保持有效电平直到DACK响应,适合连续数据流 音频I2S、高速ADC
边沿触发 DREQ上升沿或下降沿触发一次传输,适合单次事件 GPIO事件、按键中断

3.4 地址发生器(Address Generator)

地址发生器是DMA控制器的“计算核心”,负责在每次传输后自动更新源地址和目的地址。常见的地址更新模式包括:

  • 递增模式(Increment):地址每次增加传输宽度(如4字节),用于连续内存块传输。
  • 递减模式(Decrement):地址每次减少传输宽度,用于反向扫描或栈操作。
  • 固定模式(Fixed):地址保持不变,用于访问固定寄存器或FIFO。
  • 循环模式(Circular):地址到达边界后回绕到起始地址,用于环形缓冲区。
地址对齐要求: 大多数DMA控制器要求源地址和目的地址与传输宽度对齐。例如,32位传输时地址必须4字节对齐。未对齐的地址可能导致总线错误或性能下降,驱动中需通过dma_set_addr_alignment()或手动对齐处理。

3.5 DMA传输流程

一次完整的DMA传输经历四个阶段:请求 → 响应 → 传输 → 完成。下图展示了各阶段的时序关系:

DMA传输流程时序图 DMA传输流程:请求 → 响应 → 传输 → 完成 ① 请求 外设置位DREQ ② 响应 DMA置位DACK ③ 传输 数据搬移 ④ 完成 中断/回调 请求阶段 外设将DREQ置为有效电平 DMA控制器采样到请求 响应阶段 仲裁器分配总线 DMA置位DACK应答 传输阶段 地址发生器计算地址 数据在源与目的间搬移 传输计数递减 完成阶段 传输计数归零 产生传输完成中断 驱动回调处理数据 传输流程关键细节 • 请求阶段:外设通过DREQ线发起请求,DMA控制器采样到有效电平后进入仲裁。 • 响应阶段:仲裁器根据优先级选择通道,DMA控制器置位DACK并获取总线控制权。 • 传输阶段:地址发生器按配置模式更新地址,数据在源与目的之间直接搬移,CPU可并行执行其他任务。 • 完成阶段:传输计数归零后,DMA控制器清除通道忙标志,可选产生中断通知CPU。

3.6 传输流程详细说明

3.6.1 请求阶段

外设(如UART、SPI、ADC)在准备好数据或需要数据时,通过硬件请求线DREQ向DMA控制器发出传输请求。请求信号可以是电平或边沿触发,具体由外设接口协议决定。

3.6.2 响应阶段

DMA控制器内部的仲裁器检测到DREQ有效后,根据通道优先级和当前总线状态决定是否响应。若总线空闲且该通道优先级最高,DMA控制器执行以下操作:

  1. 置位DACK信号,通知外设请求已被接受。
  2. 获取系统总线控制权(通过HOLD/HLDA握手或直接总线主控)。
  3. 锁定当前通道,防止其他通道干扰。

3.6.3 传输阶段

这是DMA的核心执行阶段。地址发生器根据SAR和DAR的配置模式生成当前总线地址,数据在源与目的之间直接搬移。每次传输完成后:

  • 地址寄存器按配置模式更新(递增/递减/固定)。
  • 传输计数寄存器(TCR)递减。
  • 若配置为突发模式,连续传输多个数据单元后才释放总线。
突发传输与总线延迟: 突发传输(Burst Transfer)允许DMA连续占用总线传输多个数据单元,减少总线切换开销。但过长的突发会阻塞CPU和其他外设的总线访问。驱动中需根据系统实时性要求合理设置突发大小(通常为4、8、16个数据单元)。

3.6.4 完成阶段

当传输计数寄存器(TCR)递减到零时,DMA控制器认为本次传输完成。此时:

  • 清除通道的忙标志位。
  • 若控制寄存器中使能了传输完成中断,则向中断控制器发送中断请求。
  • 释放总线控制权,返回空闲状态。

驱动中的中断服务程序(ISR)读取状态寄存器确认传输完成,然后调用回调函数处理数据或启动下一次传输。

3.7 传输模式对比

传输模式 描述 总线占用 典型应用
单次传输(Single) 每次请求只传输一个数据单元 低 低速外设、GPIO
突发传输(Burst) 一次请求连续传输多个数据单元 高 高速ADC、音频流
链表传输(Scatter-Gather) 通过描述符链表管理多个不连续内存块 中 网络包、存储设备
循环传输(Circular) 地址回绕,连续循环传输 持续 环形缓冲区、实时采样
驱动开发提示: 在Linux内核中,DMA引擎驱动通过dmaengine_prep_slave_single()、dmaengine_prep_dma_cyclic()等API配置传输模式。理解硬件控制器的通道和请求线映射关系,是正确调用这些API的前提。