2. DMA控制器基础:eDMA模块架构、通道、TCD结构详解

S32K3系列MCU集成了增强型直接内存访问控制器(eDMA),该模块能够在无需CPU干预的情况下,高效地在存储器与存储器、存储器与外设之间传输数据。理解eDMA的模块架构、通道机制以及传输控制描述符(TCD)是进行高效DMA驱动移植与中断优先级协同设计的基础。本节将深入剖析这些核心概念。

2.1 eDMA模块架构概览

eDMA控制器由两个主要引擎组成:传输引擎(DMA Engine)和通道仲裁引擎(Channel Arbitration Engine)。传输引擎负责执行实际的数据搬运操作,而通道仲裁引擎则负责在多个请求通道之间决定下一个服务对象。

架构要点: eDMA采用双引擎设计,将“做什么”(传输控制)与“谁先做”(通道仲裁)分离,提高了系统的并发处理能力和灵活性。
eDMA模块架构图 eDMA模块架构图 系统总线接口(AHB / AXI) 传输引擎(DMA Engine) 地址计算单元 字节对齐逻辑 TCD 读取/解析 传输完成逻辑 数据缓冲与握手控制 通道仲裁引擎 固定优先级仲裁 轮询优先级仲裁 通道请求优先级比较器 通道使能状态寄存器 外设/软件 DMA 请求(32通道)

2.2 DMA通道(Channel)

eDMA模块支持多达32个独立的DMA通道(具体数量取决于芯片型号,S32K3系列通常为16或32通道)。每个通道都可以独立配置,用于服务一个特定的外设或软件触发的数据传输请求。

通道属性 说明
通道编号 0 ~ 31,每个通道对应一个唯一的优先级和TCD槽位。
请求源 每个通道可以映射到一个外设请求(如LPUART、SPI、ADC)或由软件触发。
优先级 支持固定优先级(通道号越小优先级越高)和轮询优先级两种模式。
使能状态 通过通道控制寄存器(DCHPRIn)独立使能或禁止。
中断关联 每个通道在传输完成或发生错误时,可产生中断请求至INTC。
移植提示: 在项目移植时,务必检查目标芯片的通道总数。如果原项目使用了32个通道,而目标芯片只有16个,则需要重新规划通道分配,将不常用的外设DMA请求合并或改用软件触发。

2.3 传输控制描述符(TCD)结构详解

TCD是eDMA的核心数据结构,每个DMA通道都关联一个TCD。TCD定义了该通道传输的所有参数,包括源地址、目的地址、传输大小、传输模式以及链接通道等。TCD存储在系统内存中,eDMA引擎在执行传输时会自动从内存中加载TCD。

一个标准的TCD结构体定义如下(以S32K3 SDK为例):

typedef struct {
    uint32_t SADDR;      // 源地址
    uint16_t SOFF;       // 每次传输后源地址偏移量
    uint16_t ATTR;       // 传输属性(源/目的数据大小、模数)
    uint32_t NBYTES;     // 每次服务请求传输的字节数
    uint32_t SLAST;      // 主循环结束后源地址回退/调整量
    uint32_t DADDR;      // 目的地址
    uint16_t DOFF;       // 每次传输后目的地址偏移量
    uint16_t CITER;      // 当前主循环迭代次数(开始值)
    uint32_t DLAST_SGA;  // 主循环结束后目的地址回退/调整量 或 下一TCD地址
    uint16_t CSR;        // 控制与状态寄存器
    uint16_t BITER;      // 主循环迭代次数(开始值)
} tcd_t;
TCD结构图 TCD(传输控制描述符)结构图 TCD 内存布局(32字节对齐) SADDR (32-bit) 源地址 SOFF (16-bit) 源地址偏移 ATTR (16-bit) 传输属性 NBYTES (32-bit) 每次服务传输字节数 SLAST (32-bit) 主循环结束源地址调整 DADDR (32-bit) 目的地址 DOFF (16-bit) 目的地址偏移 CITER (16-bit) 当前迭代次数 DLAST_SGA (16-bit) 目的调整/下一TCD CSR (16-bit) 控制/状态 注:BITER 在初始化时与 CITER 相同,用于循环传输的重新加载。

2.4 TCD关键字段详解

理解TCD中每个字段的作用是配置DMA传输的关键。以下是对核心字段的详细解释:

  • SADDR / DADDR: 源地址和目的地址。支持8位、16位、32位对齐访问。
  • SOFF / DOFF: 每次传输后,源地址和目的地址的偏移量。正数表示地址递增,负数表示递减,0表示地址不变。
  • NBYTES: 每次DMA服务请求(即一次外设触发或软件触发)传输的字节数。可以配置为1、2、4、16、32等。
  • SLAST / DLAST_SGA: 当主循环迭代次数(CITER)减为0时,对源地址和目的地址进行的最终调整。常用于环形缓冲区或数据打包/解包。
  • CITER / BITER: 当前迭代次数和开始迭代次数。CITER在每次传输后递减,当减为0时,传输完成或自动重载BITER的值。
  • CSR: 控制与状态寄存器,包含通道完成标志、中断使能、通道链接使能等控制位。
常见配置错误: 在配置NBYTES时,如果外设FIFO深度为4,而NBYTES配置为1,会导致频繁触发DMA请求,降低总线效率。建议将NBYTES配置为与外设FIFO深度匹配的值(如16字节)。

2.5 传输模式与TCD链接

eDMA支持多种传输模式,通过TCD中的CSR寄存器进行配置:

传输模式 配置方式 典型应用场景
基本传输 单次TCD,CITER减为0后停止 单次数据块传输(如ADC采样结果读取)
循环传输 CITER减为0后自动重载BITER 周期性数据采集、PWM波形生成
通道链接 主TCD完成后,自动加载DLAST_SGA指向的下一TCD 复杂数据流处理(如音频编解码)
散聚传输 通过链接多个TCD实现非连续内存块的传输 网络数据包处理、文件系统操作
TCD链接与传输模式 TCD链接与传输模式 TCD 0 主传输 DLAST_SGA = &TCD1 TCD 1 链接传输 DLAST_SGA = &TCD2 TCD 2 最终传输 DLAST_SGA = 0 通道链接机制 当TCD0的CITER减为0时,eDMA自动加载DLAST_SGA指向的TCD1,实现无缝传输切换。

2.6 项目移植中的TCD配置要点

在进行DMA驱动移植时,TCD的配置需要特别注意以下几点:

  1. 内存对齐: TCD结构体必须32字节对齐(即地址的低5位为0),否则eDMA引擎无法正确加载TCD。
  2. 字节序: S32K3使用小端模式,如果从大端平台移植代码,需要检查TCD中多字节字段的赋值顺序。
  3. 缓存一致性: 如果启用了数据缓存(DCache),在修改TCD后必须执行缓存清理操作,确保eDMA读取到的是最新数据。
  4. 中断标志: 在中断服务函数中,必须读取DMA完成标志寄存器(DCHPRIn)并写1清除,否则无法触发下一次中断。
移植实战建议: 建议在初始化阶段使用结构体赋值方式一次性配置TCD,而不是逐个寄存器写入。这样可以减少代码量,并利用编译器的对齐检查功能。