2. DMA控制器基础:eDMA模块架构、通道、TCD结构详解
S32K3系列MCU集成了增强型直接内存访问控制器(eDMA),该模块能够在无需CPU干预的情况下,高效地在存储器与存储器、存储器与外设之间传输数据。理解eDMA的模块架构、通道机制以及传输控制描述符(TCD)是进行高效DMA驱动移植与中断优先级协同设计的基础。本节将深入剖析这些核心概念。
2.1 eDMA模块架构概览
eDMA控制器由两个主要引擎组成:传输引擎(DMA Engine)和通道仲裁引擎(Channel Arbitration Engine)。传输引擎负责执行实际的数据搬运操作,而通道仲裁引擎则负责在多个请求通道之间决定下一个服务对象。
架构要点: eDMA采用双引擎设计,将“做什么”(传输控制)与“谁先做”(通道仲裁)分离,提高了系统的并发处理能力和灵活性。
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;
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实现非连续内存块的传输 | 网络数据包处理、文件系统操作 |
2.6 项目移植中的TCD配置要点
在进行DMA驱动移植时,TCD的配置需要特别注意以下几点:
- 内存对齐: TCD结构体必须32字节对齐(即地址的低5位为0),否则eDMA引擎无法正确加载TCD。
- 字节序: S32K3使用小端模式,如果从大端平台移植代码,需要检查TCD中多字节字段的赋值顺序。
- 缓存一致性: 如果启用了数据缓存(DCache),在修改TCD后必须执行缓存清理操作,确保eDMA读取到的是最新数据。
- 中断标志: 在中断服务函数中,必须读取DMA完成标志寄存器(DCHPRIn)并写1清除,否则无法触发下一次中断。
移植实战建议: 建议在初始化阶段使用结构体赋值方式一次性配置TCD,而不是逐个寄存器写入。这样可以减少代码量,并利用编译器的对齐检查功能。