2. S32K3 DMA控制器架构:DMA模块内部结构、通道、传输请求、源/目标地址、传输宽度与突发大小
S32K3系列MCU集成了增强型DMA控制器(eDMA),其设计旨在高效处理大量数据搬移任务,无需CPU持续干预。理解其内部架构是进行RTD驱动配置与项目移植的基础。本章将深入剖析DMA模块的核心组件、传输机制与关键参数。
2.1 DMA模块内部结构
S32K3的eDMA控制器由两个主要引擎构成:传输引擎(Transfer Engine, TE)和通道仲裁引擎(Channel Arbitration Engine, CAE)。它们协同工作,实现从请求到传输完成的完整流程。
核心组件:
- DMA通道(DMA Channel):每个通道包含一组寄存器(源地址、目标地址、传输控制描述符TCD),用于定义一次完整的DMA传输任务。
- 传输控制描述符(TCD):通道的核心数据结构,存储了传输的所有配置信息,包括地址、传输大小、偏移量、链接通道等。
- 通道仲裁引擎(CAE):当多个通道同时请求服务时,CAE根据优先级(固定优先级或轮询)选择下一个执行的通道。
- 传输引擎(TE):实际执行数据搬移的硬件单元,负责从源地址读取数据并写入目标地址。
- DMA请求多路选择器(DMAMUX):将外设的DMA请求信号(如ADC转换完成、LPUART接收数据)路由到指定的DMA通道。
2.2 DMA通道与传输请求
每个DMA通道都对应一个唯一的TCD,TCD定义了传输的全部细节。传输请求是启动DMA传输的触发信号。
2.2.1 通道特性
- 通道数量:S32K3系列根据具体型号,通常提供16至64个DMA通道。
- 通道优先级:支持固定优先级(Fixed Priority)和轮询优先级(Round-Robin Priority)两种仲裁模式。
- 通道链接:一个通道传输完成后,可以自动触发另一个通道(Minor Loop或Major Loop链接),实现复杂的数据处理链。
2.2.2 传输请求类型
| 请求类型 | 触发源 | 典型应用场景 |
|---|---|---|
| 外设硬件请求 | 外设模块(ADC、LPUART、SPI、定时器等) | ADC转换结果搬移、UART接收FIFO数据读取 |
| 软件触发请求 | CPU通过写寄存器启动 | 内存到内存拷贝、初始化数据块 |
| 链式触发请求 | 其他DMA通道传输完成事件 | 多通道级联传输、乒乓缓冲切换 |
移植要点:在从S32K1移植到S32K3时,需注意DMAMUX的配置方式不同。S32K3的DMAMUX支持更灵活的触发源选择和同步功能,RTD驱动中通过
Dma_Ip_Init() 和 Dma_Ip_ConfigChannel() 进行配置。
2.3 源/目标地址与传输宽度
DMA传输的核心是定义数据从哪里来(源地址),到哪里去(目标地址),以及每次传输多少数据(传输宽度)。
2.3.1 地址配置
- 源地址(Source Address):数据读取的起始地址。可以是外设数据寄存器地址或内存地址。
- 目标地址(Destination Address):数据写入的起始地址。可以是内存地址或外设数据寄存器地址。
- 地址偏移(Address Offset):每次传输后,源地址和目标地址的更新方式。支持固定地址(用于外设FIFO)、递增地址(用于内存缓冲区)或递减地址。
2.3.2 传输宽度(Transfer Width)
传输宽度定义了单次总线访问的数据大小。S32K3 eDMA支持以下宽度:
| 宽度枚举 | 数据大小 | 典型用途 |
|---|---|---|
DMA_TRANSFER_WIDTH_8BIT |
1字节(8位) | UART字符传输、8位外设寄存器访问 |
DMA_TRANSFER_WIDTH_16BIT |
半字(16位) | 定时器捕获值、16位ADC数据 |
DMA_TRANSFER_WIDTH_32BIT |
字(32位) | 内存拷贝、32位外设寄存器(如SPI FIFO) |
对齐要求:源地址和目标地址必须与传输宽度对齐。例如,32位传输要求地址按4字节对齐。未对齐的访问可能导致总线错误或数据损坏。在RTD配置中,需确保
SrcAddr 和 DestAddr 满足对齐约束。
2.4 突发大小(Burst Size)
突发大小定义了DMA在一次总线仲裁周期内连续传输的数据单元数量。合理配置突发大小可以显著提高总线利用率和传输效率。
2.4.1 突发大小与传输循环
DMA传输分为两个循环层次:
- Minor Loop(小循环):一次突发传输完成的数据量。由
NBYTES寄存器中的SMOD和SSIZE/DSIZE共同决定。 - Major Loop(大循环):整个DMA传输任务完成的数据量。由
CITER(当前迭代次数)和BITER(起始迭代次数)控制。
突发大小与传输宽度的关系如下:
| 突发大小(Burst Size) | 含义 | 示例(传输宽度=32位) |
|---|---|---|
| 1 | 单次传输 | 每次传输4字节 |
| 4 | 4次突发 | 一次仲裁传输16字节 |
| 8 | 8次突发 | 一次仲裁传输32字节 |
| 16 | 16次突发 | 一次仲裁传输64字节 |
2.5 关键参数配置示例(RTD驱动)
以下代码片段展示了在RTD驱动中如何配置DMA通道的源地址、目标地址、传输宽度和突发大小:
// 使用RTD API配置DMA通道
Dma_Ip_ConfigChannel(DMA_INSTANCE, DMA_CHANNEL_0, &dmaChannelConfig);
// 假设dmaChannelConfig结构体定义如下:
dmaChannelConfig.transferSize = DMA_TRANSFER_SIZE_32BIT; // 传输宽度:32位
dmaChannelConfig.srcAddr = (uint32_t)&ADC0->R[0]; // 源地址:ADC结果寄存器
dmaChannelConfig.destAddr = (uint32_t)&adcBuffer[0]; // 目标地址:内存缓冲区
dmaChannelConfig.srcOffset = 0; // 源地址不递增(外设固定地址)
dmaChannelConfig.destOffset = 4; // 目标地址每次递增4字节
dmaChannelConfig.minorLoopBytes = 16; // 小循环字节数:16字节
dmaChannelConfig.majorLoopCount = 100; // 大循环次数:100次
// 注意:minorLoopBytes / transferSize = 16 / 4 = 4,即突发大小为4
移植经验:
- 在配置
minorLoopBytes时,必须确保其值是传输宽度的整数倍,且不超过TCD中NBYTES字段的最大值(通常为1024字节)。 - 对于外设到内存的传输,源地址通常设置为不递增(
srcOffset = 0),目标地址递增;内存到外设则相反。 - 突发大小不宜过大,否则会长时间占用总线,影响其他高优先级任务(如中断响应)。建议根据系统实时性要求进行权衡。