2. DMA 硬件架构:控制器、通道与请求机制

DMA(Direct Memory Access)硬件架构是驱动开发与内存管理优化的物理基础。理解 DMA 控制器内部结构、通道(Channel)与请求(Request)机制、以及源地址与目的地址寄存器的运作原理,是编写高效、稳定 DMA 驱动的第一步。本章将从硬件寄存器级视角,拆解 DMA 引擎的核心组件。

2.1 DMA 控制器内部结构

一个典型的 DMA 控制器内部由多个功能单元组成,它们协同完成从请求仲裁到数据传输的全流程。下图展示了标准 DMA 控制器的内部模块划分与数据通路。

DMA 控制器内部结构框图 DMA 控制器内部结构框图 控制与状态寄存器 CSR / CR / SR 通道仲裁器 优先级 / 轮询 通道阵列 (Channel Array) 通道 0 SAR / DAR / CBR 通道 1 SAR / DAR / CBR 通道 2 SAR / DAR / CBR 通道 3 SAR / DAR / CBR 总线主控接口 AHB / AXI / PCIe 外设请求接口 DREQ / DACK 说明 SAR: 源地址寄存器 DAR: 目的地址寄存器 CBR: 传输计数寄存器

DMA 控制器内部主要包含以下关键模块:

模块 功能描述 驱动关注点
控制与状态寄存器组 管理全局使能、中断状态、错误标志、传输类型(内存-内存/内存-外设) 初始化时配置传输模式;中断处理时读取状态位清除错误
通道仲裁器 在多个活跃通道间仲裁总线使用权,支持固定优先级或轮询调度 高优先级通道用于实时外设(如音频);避免低优先级通道饿死
通道阵列 每个通道独立拥有源地址寄存器(SAR)、目的地址寄存器(DAR)、传输计数寄存器(CBR) 驱动为每个传输任务分配独立通道;通道复用需保存/恢复上下文
总线主控接口 作为总线主设备发起读写事务,支持突发传输(Burst)和地址递增模式 配置突发长度以匹配系统缓存行大小;地址对齐影响传输效率
外设请求接口 接收外设的 DMA 请求信号(DREQ),返回应答信号(DACK) 外设驱动需正确断言 DREQ;DMA 驱动需配置请求极性及握手协议
工程提示: 在嵌入式 SoC 中,DMA 控制器通常挂载在 AHB 或 AXI 总线上。驱动开发时,务必查阅芯片参考手册中 DMA 控制器的 基地址偏移 和 通道寄存器映射,不同厂商(如 STM32、NXP i.MX、TI OMAP)的寄存器布局差异较大。

2.2 通道(Channel)与请求(Request)机制

通道是 DMA 控制器内部独立的硬件执行单元,每个通道可以独立配置并执行一次数据传输任务。请求机制则定义了外设如何触发 DMA 传输。

2.2.1 通道的生命周期与状态机

一个 DMA 通道从配置到完成传输,经历以下状态转换:

  1. 空闲(Idle):通道未配置,寄存器为默认值。
  2. 配置(Configured):驱动写入 SAR、DAR、CBR 及控制字,通道就绪。
  3. 等待请求(Waiting for Request):使能通道后,等待外设 DREQ 或软件触发。
  4. 传输中(Transferring):获得总线控制权,逐字节或逐突发传输数据。
  5. 完成(Completed):CBR 递减至零,触发中断或设置完成标志。
  6. 错误(Error):总线错误、地址对齐异常或超时,进入错误状态。
驱动避坑: 在传输完成中断处理函数中,必须读取通道的状态寄存器确认传输是否真正完成,而非仅依赖中断标志。某些 DMA 控制器在总线错误时也会触发“完成中断”,导致数据损坏而不自知。

2.2.2 请求类型与触发方式

DMA 请求分为硬件请求和软件请求两大类,具体差异如下表:

请求类型 触发源 典型应用场景 驱动配置要点
硬件请求(Hardware DMA Request) 外设引脚 DREQ 电平/边沿 UART RX/TX、SPI、I2S 音频、ADC 采样 配置请求极性(高电平/上升沿)、请求屏蔽、外设编号映射
软件请求(Software DMA Request) 写触发寄存器(SWT) 内存-内存拷贝、校验和计算、加密加速 无需外设参与;注意软件触发后需轮询完成标志
链式请求(Linked List / Descriptor) 前一个传输完成自动触发下一个 高速数据流(以太网、视频帧)、环形缓冲区 配置描述符链表;注意内存一致性(Cache Coherency)

2.2.3 多通道仲裁与优先级

当多个通道同时请求传输时,仲裁器决定总线使用权。常见仲裁策略:

  • 固定优先级(Fixed Priority):通道编号越小优先级越高。适用于实时性要求严格的外设(如音频播放)。
  • 轮询(Round-Robin):所有通道平等共享总线带宽。适用于多个非实时外设同时工作。
  • 混合模式(Hybrid):高优先级通道使用固定优先级,其余通道使用轮询。
性能指标: 在 4 通道 DMA 控制器中,若通道 0(音频)配置为固定最高优先级,通道 1-3 配置为轮询,音频传输延迟可控制在 2-3 个总线时钟周期内,而其他通道的带宽分配误差不超过 5%。

2.3 源地址与目的地址寄存器

源地址寄存器(SAR)和目的地址寄存器(DAR)是每个 DMA 通道最核心的配置字段。它们决定了数据从哪里来、到哪里去,以及地址如何更新。

2.3.1 地址寄存器结构

典型的 32 位 DMA 控制器中,SAR 和 DAR 为 32 位宽,支持 8/16/32 位数据宽度。部分高端控制器(如 ARM PL330)支持 64 位地址。寄存器位域定义如下:

// 以 32 位 DMA 控制器为例
struct dma_channel_regs {
    uint32_t sar;   // 源地址寄存器 (Source Address Register)
    uint32_t dar;   // 目的地址寄存器 (Destination Address Register)
    uint32_t cbr;   // 传输计数寄存器 (Count Byte Register)
    uint32_t cr;    // 控制寄存器 (Control Register)
    uint32_t sr;    // 状态寄存器 (Status Register)
};

// 控制寄存器关键位域
#define DMA_CR_SRC_INC    (1 << 0)  // 源地址递增
#define DMA_CR_DST_INC    (1 << 1)  // 目的地址递增
#define DMA_CR_SRC_WIDTH  (1 << 2)  // 源数据宽度: 0=8bit, 1=32bit
#define DMA_CR_DST_WIDTH  (1 << 3)  // 目的数据宽度
#define DMA_CR_BURST_LEN  (0x7 << 4) // 突发长度 (0=1, 1=4, 2=8, 3=16)
#define DMA_CR_CH_EN      (1 << 31) // 通道使能

2.3.2 地址更新模式

每次传输后,SAR 和 DAR 的更新行为由控制寄存器中的递增/递减标志决定。常见模式:

模式 源地址更新 目的地址更新 典型场景
内存到内存 递增(+数据宽度) 递增(+数据宽度) memcpy、数据搬移
外设到内存 固定(外设 FIFO 地址不变) 递增 UART 接收、ADC 采样
内存到外设 递增 固定(外设 FIFO 地址不变) SPI 发送、DAC 输出
外设到外设 固定 固定 数字信号处理(DSP)链路
循环模式(Ring Buffer) 递增,到达边界回绕 递增,到达边界回绕 音频环形缓冲区、网络描述符

2.3.3 地址对齐与性能

地址对齐直接影响 DMA 传输效率。大多数 DMA 控制器要求源地址和目的地址对齐到数据宽度:

  • 8 位宽度:无对齐要求。
  • 16 位宽度:地址必须 2 字节对齐。
  • 32 位宽度:地址必须 4 字节对齐。
  • 64 位宽度:地址必须 8 字节对齐。
对齐错误后果: 若地址未对齐,部分 DMA 控制器会触发总线错误(Bus Error)并终止传输;另一些控制器会降级为单字节传输,导致性能下降 50% 以上。驱动中应使用 dma_set_addr_alignment() 或手动检查地址低位。

2.3.4 传输计数寄存器(CBR)与传输完成

CBR 记录剩余待传输的字节数。每次传输后,CBR 递减实际传输的字节数。当 CBR 减至 0 时,通道自动停止并触发完成中断。驱动需注意:

  • 初始值:必须等于实际传输字节数,而非数据项个数。
  • 重载:在循环模式下,CBR 到达 0 后自动重载初始值。
  • 暂停与恢复:读取 CBR 当前值可获取传输进度,用于暂停后恢复。
// 配置 DMA 通道传输 1024 字节,32 位宽度
#define BUF_SIZE 1024
#define DATA_WIDTH 4  // 32-bit

dma_channel_regs->sar = (uint32_t)src_buf;
dma_channel_regs->dar = (uint32_t)dst_buf;
dma_channel_regs->cbr = BUF_SIZE;  // 字节数
dma_channel_regs->cr  = DMA_CR_SRC_INC | DMA_CR_DST_INC |
                        DMA_CR_SRC_WIDTH | DMA_CR_DST_WIDTH |
                        (0x2 << 4) |  // 突发长度 4
                        DMA_CR_CH_EN;
调试技巧: 在传输过程中,通过调试器读取 SAR、DAR、CBR 三个寄存器的值,可以快速定位地址配置错误或传输卡死问题。例如,若 SAR 和 DAR 长时间不变,说明通道未收到请求或总线被阻塞。

2.4 本章小结

DMA 硬件架构是驱动开发与内存管理优化的基石。理解控制器内部模块划分、通道状态机、请求触发方式以及地址寄存器的更新模式,能够帮助开发者:

  • 正确初始化 DMA 通道,避免地址对齐和配置错误。
  • 合理分配通道优先级,满足实时外设的延迟要求。
  • 利用地址递增/固定模式,适配不同外设的传输需求。
  • 通过 CBR 监控传输进度,实现暂停、恢复和错误恢复。