1. 项目概述:为什么需要深入理解PDMA的AASRC模式?
在嵌入式系统开发,尤其是涉及音频、视频或高速传感器数据处理的领域,工程师们常常面临一个核心挑战:如何在不占用CPU大量资源的前提下,高效、可靠地搬运海量数据。直接内存访问(DMA)技术就是解决这一问题的“王牌”。它像一个专职的快递员,能在内存和外围设备(如ADC、DAC、McASP音频接口)之间直接搬运数据,让CPU得以抽身去处理更复杂的逻辑和算法。
然而,传统的DMA控制器功能相对固定,通常一个通道对应一个固定的数据源或目的地,处理复杂、交织的多路数据流时显得力不从心。这就引出了我们今天要深入探讨的主角——可编程DMA(PDMA),特别是其强大的AASRC(Asynchronous Sample Rate Converter)模式。如果你正在开发需要同时处理多路麦克风阵列音频、多通道传感器融合或者复杂通信协议的系统,那么理解PDMA的AASRC模式,就如同掌握了一把打开高性能数据传输大门的钥匙。
简单来说,AASRC模式将DMA的灵活性提升到了一个新的高度。它不再局限于“一个通道,一个方向,一个地址”的简单模式,而是允许一个DMA通道通过一个可编程的“任务清单”(FIFO索引列表),按任意顺序去服务多个数据缓冲区(FIFO)。无论是处理16路独立的音频流,还是将交织的传感器数据重新排列,AASRC模式都能游刃有余。本文将从一线工程师的视角,拆解AASRC模式的核心机制、配置细节,并结合多通道配置的实战经验,带你彻底掌握这项关键技术,避开那些手册里不会写的“坑”。
2. PDMA与AASRC模式核心架构解析
要玩转AASRC,首先得理解PDMA的基本框架和AASRC模式在这个框架中的特殊定位。PDMA可以看作一个高度可配置的数据搬运“流水线”调度中心。
2.1 PDMA通道资源与基本概念
根据技术手册,一个典型的PDMA控制器可能提供多达16个独立的接收(RX)通道和16个独立的发送(TX)通道。这里的“独立”意味着每个通道都拥有自己的一套控制寄存器、状态机和数据路径,可以并行工作。每个通道代表一个独立的数据流,其终点可以是另一个DMA控制器(如UDMA-P),也可以是像McASP这样的音频串行端口。
核心特性一:灵活的FIFO访问机制这是AASRC模式的精髓。每个通道可以被配置为以任何顺序读取或写入任何一个AASRC的FIFO。想象一下,你有16个水龙头(FIFO)在同时流水,而AASRC通道就像一个拿着水桶的工人,他可以按照一张定制清单(Ordering Table)的顺序,去1号桶接一点水,然后去8号桶,再去3号桶,完全打破物理顺序的限制。这对于音频处理中常见的“解交织”操作(比如将多路交织的音频数据分离成独立的单声道流)至关重要。
核心特性二:样本打包支持AASRC模式支持1、2、3、4字节的样本打包。这意味着它可以原生处理8位、16位、24位、32位的音频样本数据。关键在于,对于一个给定的通道,其打包样本大小是固定的。如果你配置一个通道处理24位音频(3字节),那么它从所有服务的FIFO中读取或写入的数据都会按照24位来处理。这直接与McASP等音频接口的数据格式对齐,无需CPU进行繁琐的数据重整。
核心特性三:流模式与组模式AASRC模式支持两种信号机制:流模式(Stream)和组模式(Group),每种模式对应不同的FIFO内存映射。
- 流模式:每个FIFO(最多16个)都有自己独立的DMA请求信号。通道需要等待它所关心的所有FIFO的DMA请求都就绪后,才会启动传输。这适用于需要严格同步的多路独立数据流。
- 组模式:将多个FIFO(通常是4个一组)捆绑在一起,共享一个组DMA请求信号。通道只需要等待这一个组请求信号,即可处理该组内的所有FIFO。这简化了同步逻辑,适用于那些可以批量处理的数据流。
注意:通道的流/组模式设置是全局的。一个通道一旦被设置为组模式,它就会去寻找组模式的DMA请求,并访问组模式下的FIFO地址空间;反之亦然。两者不能混用。
2.2 通道配置的核心三要素
配置一个AASRC通道,本质上是告诉PDMA三件事:何时动、动哪里、怎么动。
触发条件(何时动 - DmaReqMask): 每个通道都有一个
DmaReqMask(DMA请求掩码)。这个掩码指明了哪些DMA请求信号必须有效(触发)才能激活本通道。- 在流模式下,这是一个16位的掩码,每一位对应一个具体的FIFO(0-15)。如果通道需要服务FIFO 0, 2, 5,那么就需要将
DmaReqMask的bit0、bit2、bit5置1。通道会锁存这些请求,直到所有被掩码覆盖的请求都到齐,才启动传输。 - 在组模式下,通常只有低4位(bit3:0)有意义,因为最多只有4个组。此时,掩码中只能有一位被置1,表示通道只响应某一个特定的组请求。
- 在流模式下,这是一个16位的掩码,每一位对应一个具体的FIFO(0-15)。如果通道需要服务FIFO 0, 2, 5,那么就需要将
访问顺序(动哪里 - Ordering Table): 这是AASRC最巧妙的设计。系统维护一个或多个排序表(Ordering Table),例如
TxOrderTable0和TxOrderTable1。每个表有16个“槽位”(Slot),每个槽位存储一个FIFO的索引号(0-15)。 通道并不直接指定访问哪个FIFO,而是通过FirstSlot和LastSlot这两个参数,指定它要使用排序表中的哪一段连续槽位。PDMA会从FirstSlot指向的槽位开始,依次读取其中的FIFO索引,并访问对应的FIFO,直到LastSlot结束。- 示例:假设
TxOrderTable0的槽位0-7内容为[0, 2, 4, 6, 1, 3, 5, 7]。如果某个通道配置了FirstSlot=2,LastSlot=5,那么该通道一次触发传输访问的FIFO顺序将是:槽位2的4-> 槽位3的6-> 槽位4的1-> 槽位5的3。这完美实现了对FIFO的非顺序、可编程访问。
- 示例:假设
传输参数(怎么动 - 静态传输请求Static TR): 静态TR(Transfer Request)定义了每次触发传输的具体行为,主要包含X, Y, Z三个参数(在AASRC模式下,Z参数通常保留或用于包计数,核心是X和Y)。
- X参数(PSIL Addr 0x400[26:24]):元素大小。定义了每次访问FIFO时,读写的数据量。编码为:0=8位,1=16位,2=24位,3=32位。这必须与FIFO中存储的数据样本大小以及通道的打包设置匹配。
- Y参数(PSIL Addr 0x400[11:0]):FIFO元素计数。这是最容易误解的参数。它不是总共传输的样本数,而是整个FIFO列表(从FirstSlot到LastSlot)被处理的循环次数。
- 计算示例:假设
FirstSlot=0,LastSlot=3(即列表有4个FIFO索引),X=2(24位,3字节),Y=5。 - 每次DMA请求触发后,通道会完整地处理一遍FIFO列表:访问第0号索引FIFO,传输一个3字节样本;访问第1号索引FIFO,传输一个3字节样本;以此类推,直到第3号索引FIFO。这算一次循环。
- 由于
Y=5,上述“完整处理列表”的过程会重复5次。 - 因此,本次触发传输的总样本数 = (LastSlot - FirstSlot + 1) * Y = 4 * 5 = 20个样本。总数据量 = 20样本 * 3字节/样本 = 60字节。
- 计算示例:假设
理解这三者的关系,是正确配置AASRC通道的基础。它们共同构成了一个强大的、声明式的数据传输任务描述:“当(DmaReqMask指定的)所有信号就绪时,按照(Ordering Table指定的)顺序,对每个目标FIFO进行(Y��)循环,每次搬运(X大小的)一个数据元素。”
3. AASRC模式实战配置详解
理论清晰后,我们进入实战环节。配置一个AASRC通道,就像在编写一个硬件执行的脚本。下面我将以最常见的发送(TX)通道为例,拆解从初始化到数据传输的完整流程和关键寄存器配置。
3.1 通道初始化与配对流程
PDMA通道在上电复位后处于空闲状态。让它开始工作,需要主机(通常是ARM Cortex-A/M核)执行一个标准的“三部曲”:
步骤一:PSI-L线程配对PSI-L(Peripheral System Interconnect - Lite)是TI芯片内部的一种高效、低延迟的片上互连网络,用于DMA控制器之间的数据流连接。
- 复位后,所有PSI-L线程都是未初始化、未配对的。
- 主机需要将PDMA的目的线程(TX通道)与一个远程的源线程(通常是UDMA-P的一个通道)进行配对。这通过配置各自的PSI-L配对寄存器实现,让两者互相指向对方。
- 关键点:一旦配对成功,数据流路径就被硬连线了。UDMA-P源通道的所有数据只会发送给这个PDMA目的通道,而PDMA目的通道也只会接收来自这个UDMA-P源通道的数据。这种点对点的设计保证了数据流的确定性和隔离性。
步骤二:设置静态传输请求(Static TR)这是配置传输行为的核心。对于AASRC TX通道,我们需要关注PSIL地址0x400和0x401的寄存器。
XY_ACC_CFG(Addr 0x400):Burst(Bit 31): 在AASRC模式下通常不使用,保持为0。Acc32(Bit 30): 如果PDMA的VBUSP端口是32位宽的,且需要与某些仅支持32位访问的旧IP兼容,则置1。这会使PDMA的所有访问都以XCNT=4(即32位对齐)的方式进行。一般情况下,如果外设和总线都支持更高效的非对齐或突发访问,可以置0。X(Bits 26:24): 如前所述,设置元素大小。例如,对于24位音频,设置为2。Y(Bits 11:0): 设置FIFO列表的循环次数。需要根据你的应用场景计算。例如,如果你希望每次DMA请求为每个FIFO传输10个样本,而你的FIFO列表长度为4,那么Y应该设置为10。
Z_CFG(Addr 0x401):- 在AASRC模式下,Z字段通常不使用(保留)。但需要注意
EOL位(Bit 31),它控制数据包结束标志。通常,数据包结束由UDMA-P控制,此处可保持默认。
- 在AASRC模式下,Z字段通常不使用(保留)。但需要注意
步骤三:配置AASRC专用寄存器这是AASRC模式区别于普通XY模式的关键。
TxFifoConfig(PSIL Addr 0x405):GroupMode(Bit 31): 决定通道工作模式。0 = 流模式,1 = 组模式。DmaReqMask(Bits 15:0):务必谨慎配置。在流模式下,如果你需要服务FIFO 0, 2, 5,则应将DmaReqMask设置为(1 << 0) | (1 << 2) | (1 << 5)。在组模式下,假设使用组1,则设置DmaReqMask = (1 << 1)(仅bit1为1)。FirstSlot(Bits 19:16) &LastSlot(Bits 23:20): 定义在排序表中使用的槽位范围。值必须在0-15之间,且LastSlot >= FirstSlot。列表长度 =LastSlot - FirstSlot + 1。
填充排序表
TxOrderTable0/1(Addr 0x406, 0x407): 这两个寄存器共同构成了一个16槽位的全局表。你需要根据你的数据流需求,预先将FIFO索引写入对应的槽位。- 示例配置:假设我们有4路音频数据(FIFO 0,1,2,3),但希望PDMA以交错顺序(0,2,1,3)发送。我们可以配置:
TxOrderTable0:Entry0=0,Entry1=2,Entry2=1,Entry3=3(其余槽位可任意,但建议填充为0或已知值)。- 在
TxFifoConfig中,设置FirstSlot=0,LastSlot=3。 - 这样,每次传输都会按照0->2->1->3的顺序访问FIFO。
- 示例配置:假设我们有4路音频数据(FIFO 0,1,2,3),但希望PDMA以交错顺序(0,2,1,3)发送。我们可以配置:
步骤四:使能PSI-L目的线程最后,通过设置PSI-L配对寄存器中的使能位,来激活通道。一旦使能,通道就进入“武装”状态,静待DMA请求信号的到来。
3.2 数据传输流程与状态机
当配置完成且通道使能后,其工作流程如下:
- 等待触发:通道空闲,持续监控
DmaReqMask指定的DMA请求线。在流模式下,它会锁存每一个到来的请求,直到所有被掩码覆盖的请求都到达。在组模式下,等待指定的单个组请求。 - 触发与激活:所有必需的请求到达后,通道被激活。
- 执行传输: a. 通道根据
FirstSlot和LastSlot,从TxOrderTable中读取第一个FIFO索引(比如索引m)。 b. 根据X参数(元素大小),从内部TX通道化FIFO中读取一个数据元素(例如3字节)。 c. 根据GroupMode设置和索引m,结合PDMA内部预设的基地址和FIFO间跨度,计算出目标FIFO(第m个流模式或组模式FIFO)的确切内存映射地址。 d. 通过VBUSP内存接口,将数据写入该地址。 e. 移动到排序表的下一个槽位,重复b-d步骤,直到处理完LastSlot指定的最后一个槽位。这完成了一次列表循环。 f. 重复步骤a-e,共Y次循环。 - 完成与返回:完成所有
Y次循环后,本次DMA请求服务完毕。通道清除内部锁存的请求状态,返回空闲状态,等待下一次触发。
整个过程中,PDMA会尽可能快地执行写操作,速度受限于VBUSP总线带宽、目标FIFO的准备好信号以及与其他通道的仲裁。
3.3 多通道协同工作配置实例
假设一个音频应用场景:一个McASP接口需要输出4路立体声音频(即8个单声道)。我们使用AASRC模式的两个TX通道来实现。
- 硬件假设:PDMA有16个TX FIFO(0-15)。我们将前8个FIFO(0-7)分配给这8个单声道音频数据流。
- 目标:通道0负责输出左声道(FIFO 0,2,4,6),通道1负责输出右声道(FIFO 1,3,5,7),并且希望数据是交错排列的(L0, R0, L1, R1, L2, R2, L3, R3)。
配置方案:
全局排序表配置:
TxOrderTable0: 槽位0-7设置为[0, 1, 2, 3, 4, 5, 6, 7]。这定义了物理FIFO的访问顺序。
通道0配置(左声道):
Static TR:X=2(24位音频),Y=128(每次触发为每个FIFO传输128个样本)。TxFifoConfig:GroupMode=0(流模式)。DmaReqMask=0x00AA(二进制0000 0000 1010 1010,即FIFO 1,3,5,7的请求被忽略,FIFO 0,2,4,6的请求必须全部就绪)。注意:这里假设每个FIFO有独立请求。更常见的做法是使用一个共同的触发源(如McASP的同步事件),然后掩码只设置一位来触发,但数据仍按列表顺序搬运。具体取决于AASRC外设如何产生请求。这里为演示复杂掩码。FirstSlot=0,LastSlot=6,但步长为2?不对,列表是连续的[0,1,2,3,4,5,6,7]。如果我们只想要偶数FIFO,我们需要一个不同的列表。这揭示了排序表的真正威力:我们可以创建一个自定义列表。
- 更好的方法——自定义列表:
- 重新定义
TxOrderTable0的槽位0-3为[0, 2, 4, 6](左声道FIFO)。 - 通道0配置:
FirstSlot=0,LastSlot=3。 - 这样,通道0每次触发就只访问FIFO 0,2,4,6。
- 重新定义
通道1配置(右声道):
Static TR:X=2,Y=128。TxFifoConfig:GroupMode=0。DmaReqMask=0x0055(二进制0000 0000 0101 0101,即FIFO 0,2,4,6的请求被忽略,FIFO 1,3,5,7的请求必须全部就绪)。FirstSlot=4,LastSlot=7(假设我们将右声道FIFO索引[1,3,5,7]放在排序表槽位4-7)。
- 排序表续接:
TxOrderTable0槽位4-7设置为[1, 3, 5, 7]。
通过这种配置,两个通道可以独立工作,但共享同一个排序表的不同区段。当所有8个FIFO的数据就绪(或由同一个组事件触发)时,两个通道会同时被激活,并行地将左右声道数据搬运出去。主机只需要确保将正确的音频数据填入对应的FIFO即可。
4. 关键问题排查与调试技巧
即使理解了原理和配置,在实际调试中依然会遇到各种问题。以下是我在项目中总结的常见问题与排查思路。
4.1 数据传输不启动或数据错误
这是最常见的问题,可能的原因是多方面的。
排查清单:
DMA请求信号未到达:
- 检查:确认AASRC外设(如McASP)的DMA事件生成已正确配置并启用。使用示波器或芯片的GPIO捕获功能,监测对应的DMA请求引脚是否有脉冲。
- 检查:
TxFifoConfig.DmaReqMask设置是否正确。在流模式下,是否所有需要掩码的FIFO都产生了请求?在组模式下,是否是正确的组号? - 技巧:可以先将
DmaReqMask设置为0xFFFF(流模式)或0x000F(组模式,全组)进行测试,排除掩码配置错误。
PSI-L配对或使能失败:
- 检查:确认PDMA通道的PSI-L线程与UDMA-P的对应线程已成功配对(检查配对寄存器的值)。
- 检查:确认PSI-L目的线程的使能位已被置起。
- 技巧:查阅芯片的PSI-L映射表,确认物理连接是否正确。有时手册的图表比寄存器描述更直观。
排序表或槽位配置错误:
- 症状:数据在传输,但送到了错误的FIFO(内存地址)。
- 检查:
FirstSlot和LastSlot的值是否在0-15范围内,且LastSlot >= FirstSlot。 - 检查:
TxOrderTable中存储的FIFO索引值是否有效(0-15)。写入了一个不存在的索引(如16)会导致访问非法地址。 - 检查:通道的
GroupMode设置与排序表中索引所代表的FIFO类型是否匹配。如果通道是组模式,但排序表里填的是流模式FIFO的索引,必然出错。
静态TR参数计算错误:
- 症状:数据传输量不对,要么多了,要么少了。
- 检查:
X参数是否与数据样本的实际大小匹配?24位音频必须设为2。 - 检查:
Y参数的理解是否正确?记住,Y是列表循环次数。总样本数 =(LastSlot - FirstSlot + 1) * Y。 - 验算:结合AASRC外设的DMA请求阈值(Threshold)配置。PDMA每次触发传输的总数据量(字节)应该等于AASRC FIFO的阈值深度。例如,如果AASRC每个FIFO的DMA请求阈值是256字节,样本是24位(3字节),那么每个FIFO每次请求对应
256 / 3 ≈ 85.33个样本。由于样本数必须是整数,可能需要调整FIFO深度或Y值。
4.2 性能瓶颈分析与优化
当系统数据吞吐量达不到预期时,需要考虑以下方面:
VBUSP总线竞争:所有PDMA通道共享VBUSP内存接口。如果多个高带宽通道同时活跃,会产生仲裁延迟。
- 优化:分析数据流的关键路径,错开高优先级通道的触发时间。或者,如果芯片支持,将通道分配到不同的VBUSP端口(如果存在多个)。
排序表访问效率:如果
LastSlot - FirstSlot的值很大(即列表很长),PDMA在每次循环中都需要多次查找排序表,可能引入微小延迟。- 优化:在满足功能的前提下,尽量让每个通道使用的排序表片段连续且紧凑。避免一个通道使用非常分散的槽位。
突发传输(Burst)模式:在标准的X-Y FIFO模式下,可以启用Burst模式来提升总线效率。但在AASRC模式下,
Burst位通常保留。AASRC的效率主要依赖于其“一次触发,服务多个FIFO”的机制本身。- 注意:对于非AASRC的普通XY模式通道,如果外设和总线支持,可以尝试启用Burst模式(设置
XY_ACC_CFG[31]=1),但需遵守其限制(如不能从16位外设突发读取1字节样本)。
- 注意:对于非AASRC的普通XY模式通道,如果外设和总线支持,可以尝试启用Burst模式(设置
4.3 调试寄存器与状态监控
PDMA提供了调试/状态寄存器(如PSIL地址0x402,0x403),它们是定位问题的利器。
Y寄存器 (Addr 0x402):在AASRC模式下,它显示当前正在处理的、剩余的列表循环次数。如果传输卡住,可以查看此值是否在递减。InEvent位 (Addr 0x403[31]):指示PDMA是否正在处理一个FIFO事件。常用来判断通道是否被成功触发。Data位和XData位 (Addr 0x403[28:27]):指示内部FIFO中是否有数据等待写出。如果InEvent为高但Data为低,可能意味着数据源(UDMA-P)没有送来数据。EventCnt字段 (Addr 0x403[19:16]):显示积压的、尚未处理的DMA事件数量。如果这个值不断增长,说明PDMA处理速度跟不上事件产生速度,存在性能瓶颈。
调试流程建议:
- 配置完成后,先读取这些状态寄存器,确认通道处于空闲(
InEvent=0)且无积压事件(EventCnt=0)的预期状态。 - 触发一次数据传输后,立即读取状态。应看到
InEvent短暂变高,Y值变化,然后恢复空闲。 - 如果状态异常,结合
DmaReqMask和AASRC外设的事件状态寄存器,检查DMA请求的生成和锁存情况。
4.4 关于“Flush”和“Teardown”的注意事项
在停止或重新配置通道时,需要优雅地关闭数据流,避免数据丢失或硬件状态错乱。
- Teardown(拆解):这是主机发起的、同步的通道关闭流程。UDMA-P通过PSI-L数据通道发送
tdown信号,PDMA会在处理完当前所有已接收数据后,停止通道并反馈确认。这是推荐的关闭方式,能保证数据完整性。 - Flush(刷新):当通道因某些原因(如外设无响应)无法正常Teardown时,可以设置
Flush位。此模式下,PDMA会清空内部流水线中的数据,但不执行实际的外设写操作。这是一种强制清理状态的手段,可能会导致数据丢失,仅在调试或错误恢复时使用。 - 直接禁用:直接清除PSI-L使能位会立即复位整个通道(包括TR和配对配置),是最粗暴的方式。这要求必须同时复位对端的UDMA-P通道,否则重新配对时会出问题。仅在通道状态完全无法恢复时使用。
我的经验是,在应用程序中,总是通过UDMA-P发起Teardown流程来关闭通道。在调试阶段,如果怀疑通道“卡死”,可以先尝试Teardown,不行再考虑Flush,最后才是硬复位。
5. 接收(RX)通道配置的差异与要点
虽然我们以TX通道为例进行了详细讲解,但RX通道的AASRC模式原理完全对称,理解TX后,RX配置就水到渠成。这里仅强调几个关键差异点:
- 数据流方向:TX是从PDMA内部FIFO写到外设(AASRC的FIFO);RX是从外设(AASRC的FIFO)读到PDMA内部FIFO,再通过PSI-L发送给UDMA-P。
- 排序表:RX通道使用独立的
RxOrderTable,其配置方式与TxOrderTable完全相同。需要确保为RX通道正确配置其专用的排序表寄存器。 - 静态TR的Z参数:在RX的AASRC模式中,
Z参数(Addr 0x401[23:0])被定义为FIFO计数。它指定了多少个完整的DMA请求操作构成一个完整的数据包(Packet)。当达到Z个请求后,PDMA会发送一个EOP(包结束)指示给UDMA-P。这对于将多个DMA传输的数据打包成一个大的网络或存储包非常有用。 - EOL模式:
EOL位(Addr 0x401[31])在RX中更常用。当设置时,在完成Z次���作后,PDMA会发送EOL(链表结束)而非EOP。这用于支持CPPI(通用包处理器接口)描述符链表,允许更高效的数据块管理。 - 初始化流程:RX通道的初始化同样需要PSI-L源线程配对、设置静态TR(注意X,Y,Z参数)、配置
RxFifoConfig和RxOrderTable,最后使能线程。使能后,RX通道开始监听DMA请求。
配置RX通道时,务必再次核对GroupMode、DmaReqMask、FirstSlot/LastSlot以及排序表内容,确保其与AASRC外设的RX FIFO布局和触发逻辑一致。一个常见的错误是TX和RX使用了相同的排序表索引范围,但实际上它们指向的是不同的物理FIFO集合(TX FIFO和RX FIFO地址空间独立)。