1. 项目概述与核心价值
在嵌入式系统,尤其是高性能的实时信号处理领域,数据搬运的效率直接决定了整个系统的性能上限。CPU如果被频繁的数据拷贝任务所拖累,就无法专注于核心的计算与控制逻辑。这时,直接内存访问(DMA)技术便成为解放CPU、实现高效数据流的关键。而德州仪器(TI)在其多核DSP和SoC中广泛应用的增强型直接内存访问控制器第三代(EDMA3),则将DMA的能力提升到了一个全新的高度。它不仅仅是一个简单的数据搬运工,更是一个配备了复杂调度、优先级管理和错误处理机制的“数据交通指挥中心”。
今天,我想结合多年的嵌入式开发经验,深入聊聊EDMA3控制器中最核心、也最容易让人困惑的两个机制:中断处理与事件队列。很多开发者初次接触EDMA3时,往往只关注如何配置一个通道完成一次传输,但当系统中有数十个外设、上百个数据缓冲区需要并发、实时地搬运时,如何确保关键数据不丢失、如何高效响应传输完成事件、如何诊断数据流堵塞,就成了必须面对的难题。理解中断与队列,正是解决这些难题的钥匙。
这篇文章适合所有正在或即将使用TI C6000系列DSP、OMAP、Sitara等平台的嵌入式软件工程师、驱动开发者和系统架构师。无论你是想优化现有的EDMA3使用模式,还是正在为复杂的实时数据流设计发愁,相信本文对底层原理的拆解和实战经验的分享,都能给你带来直接的帮助。我们将绕过手册中冰冷的寄存器描述,从系统设计的角度,看看EDMA3如何像一个精密的流水线一样,协调中断、队列与传输控制器,实现可靠高效的数据搬运。
2. EDMA3中断处理机制深度解析
中断是CPU与EDMA3控制器“对话”的主要方式。一次DMA传输的结束,或是一个错误的发生,都需要通过中断来通知CPU进行后续处理(如启动下一次传输、处理接收到的数据或进行错误恢复)。EDMA3的中断系统设计精巧,但也因其灵活性而略显复杂。
2.1 中断信号的产生与传递路径
让我们先厘清一个完整的中断信号是如何从EDMA3传递到CPU的。这个过程涉及多层寄存器协作,理解它对于后续的调试至关重要。
传输完成码(TCC)是起点:每个EDMA3传输请求(TR)在参数集(PaRAM)中都会配置一个传输完成码(TCC),范围通常是0-63。你可以把它理解为这次传输的“身份证号”。当传输完成(无论是正常完成还是早期完成),EDMA3通道控制器(CC)就会根据这个TCC值,去设置一个对应的标志位。
中断挂起寄存器(IPR)—— 中断的“公告板”:这个“标志位”就设置在中断挂起寄存器(IPR)中。IPR是一个位图寄存器,每一位(例如IPR.E31)对应一个TCC值。当TCC=31的传输完成时,IPR.E31位就会被硬件自动置1,表示“有一个身份证号为31的传输完成了,正在等待处理”。这里有一个关键点:IPR的位与DMA通道号没有固定绑定关系。通道0的传输完全可以配置TCC=31,这样完成时设置的就是IPR.E31,而不是IPR.E0。这种解耦设计提供了极大的灵活性,允许不同通道共享同一个中断服务例程(ISR),或者一个通道在不同情况下触发不同的中断。
中断使能寄存器(IER)—— 中断的“开关”:IPR位被置1,并不意味着中断信号一定会送到CPU。这还需要通过中断使能寄存器(IER)的许可。IER的结构与IPR一一对应。只有当IER的某一位(如IER.E31)也为1时,对应的IPR位(IPR.E31)被置1才会真正导致一个中断脉冲信号产生。IER给了软件动态控制哪些TCC可以触发中断的能力,而不影响IPR的状态记录。
DMA区域访问使能寄存器(DRAE)—— 区域管理的“大门”:在支持多核或分区操作的复杂SoC中,EDMA3的寄存器往往被划分为多个“影子区域”,每个区域可能由不同的CPU核或主设备独立管理。DRAE寄存器就是控制某个CPU是否有权访问(包括读和写)特定影子区域中断寄存器(IER, IPR等)的总开关。这是一个在系统初始化时必须谨慎配置且通常保持静态的寄存器。手册中特别强调的例子非常经典:假设DMA通道0的传输使用了TCC=31,那么为了这个通道能正常工作和产生中断,你不仅要使能通道0本身(这通常通过事件寄存器等控制),还必须确保DRAE中同时使能了位0(对应通道0的访问)和位31(对应IPR.E31/IER.E31的访问)。如果只使能了位0而没使能位31,传输可以发生,但完成中断将无法被正确设置或响应,造成难以察觉的Bug。
中断评估寄存器(IEVAL)—— 手动“敲门”工具:在某些特殊的软件架构下,ISR可能不会服务所有已使能的中断。例如,ISR只处理高优先级中断,而将低优先级中断留给主循环查询。这时,如果ISR退出时,IPR中仍有已使能但未处理的低优先级中断位为1,由于中断脉冲只在“无中断”到“有中断”的跳变沿产生,这些残留的中断将无法再次触发CPU中断。IEVAL寄存器就是解决这个问题的“后门”。向IEVAL.EVAL位写1,会强制EDMA3 CC重新评估当前IPR和IER的状态。如果发现有任何已使能的中断仍处于挂起状态(IER & IPR != 0),就会立即再产生一个中断脉冲。但必须注意:当IPR读数为0时,绝对不能写IEVAL,否则会产生虚假的中断脉冲。
2.2 中断服务例程(ISR)的设计策略与避坑指南
编写EDMA3的中断服务程序,远不是简单地清除标志位那么简单。你必须考虑到中断的并发性、重入性以及效率问题。手册提供了两种伪代码示例,这恰恰反映了两种不同的设计哲学和适用场景。
策略一: exhaustive(穷举式)ISR这种策略的伪代码如下,其核心思想是在一次ISR调用中,彻底清空当前所有挂起的中断。
1. 读取中断挂起寄存器(IPR)。 2. 根据IPR中的位,执行相应的操作(例如,处理数据、启动下一次传输)。 3. 写入中断挂起清除寄存器(ICR),清除刚刚处理过的IPR位。 4. 再次读取IPR: (a) 如果IPR不等于0,则跳回步骤2(这意味着在步骤2到步骤4之间,又有新的中断事件发生了)。 (b) 如果IPR等于0,退出ISR。- 优点: 能够确保在一次中断响应中处理完所有累积的事件,中断响应延迟相对可预测。
- 缺点: 如果中断非常频繁,ISR可能执行时间过长,导致其他低优先级中断被阻塞,影响系统实时性。这就是手册所说的“更高的延迟”。
- 适用场景: 中断源相对固定,中断处理逻辑简单、耗时短,或者系统对处理完所有事件有强实时性要求。
策略二: 非穷举式ISR配合IEVAL这种策略允许ISR只处理它关心的部分中断,并在退出前通过IEVAL确保未处理的中断不会丢失。
1. 进入ISR。 2. 读取IPR。 3. 对于IPR中你希望服务的条件(位): (a) 执行应用所需的操作。 (b) 清除已服务条件的位(其他位可能仍被设置,并且在步骤2之后可能有其他传输完成并设置了TCC)。 4. 在退出ISR前,再次读取IPR: (a) 如果IPR等于0,则退出ISR。 (b) 如果IPR不等于0,则设置IEVAL.EVAL位。这样在退出ISR时,如果任何已使能的中断仍处于挂起状态,将会触发一个新的中断。- 优点: ISR执行时间短且可控,适合处理高优先级事件,将低优先级事件留给下一次中断或主循环。
- 缺点: 可能引入“竞态条件”。例如,在步骤4读取IPR为0之后、退出ISR之前的极短时间内,一个新中断到达并设置了IPR位。由于IPR刚刚被读为0,ISR不会设置IEVAL,这个新中断就可能丢失,直到下一个中断事件发生才会被处理。虽然概率低,但在超高频率中断下需考虑。
- 实战心得: 在复杂的多通道EDMA3应用中,我通常采用一种混合策略。为高实时性通道(如音频DMA)使用穷举式ISR,确保每个数据块都被及时处理。为低实时性、批量传输的通道使用非穷举式ISR,并在其中根据IPR值判断,如果挂起的中断数量超过某个阈值,则进行批量处理,否则设置IEVAL退出。同时,务必在清除IPR位(写ICR)之前完成所有与该中断相关的数据操作,因为清除操作可能立即允许该通道的下一次传输和中断触发。
2.3 错误中断:系统健康的“哨兵”
除了传输完成中断,EDMA3还提供了一个全局的错误中断(EDMA3_CC0_ERRINT)。这是一个非常重要的调试和可靠性保障机制。它会在以下四种情况发生时被触发:
- DMA事件丢失: 外部事件速率超过EDMA3 CC的处理能力,事件被丢弃。状态记录在事件丢失寄存器(EMR)。
- QDMA事件丢失: 类似于DMA,状态在QDMA事件丢失寄存器(QEMR)。
- 队列阈值超限: 事件队列中的事件数量超过了预设的水位阈值。状态在CCERR寄存器。
- TCC错误: outstanding的、期望返回完成码的传输请求超过了最大限制(31个)。状态同样在CCERR。
错误中断与完成中断的一个关键区别是:错误中断没有类似IER的使能屏蔽寄存器。只要错误寄存器(EMR, QEMR, CCERR)中有任何位被置1,错误中断就会一直保持断言状态。它也只会在“无错误”到“有错误”的跳变沿产生脉冲。同样,EDMA3 CC也提供了错误评估寄存器(EEVAL),用于手动重新评估错误状态并产生中断脉冲。
重要提示: 强烈建议在系统初始化时,就为EDMA3错误中断配置好ISR。这远比软件轮询查询错误状态更高效,也是发现潜在实时性问题的第一道防线。在错误ISR中,应详细记录错误类型、通道和队列信息,这对于后期调试“幽灵般”偶现的数据丢失问题至关重要。
3. 事件队列:EDMA3的流量控制与调度核心
如果说中断机制是EDMA3与CPU的通信协议,那么事件队列就是EDMA3控制器内部的“交通枢纽”。所有来自外部触发、手动触发、链式触发和QDMA触发的事件,都要经过这个枢纽的调度,才能被转化为实际的传输请求(TR)提交给传输控制器(TC)。
3.1 队列的工作原理与通道映射
每个事件队列本质上是一个深度为16的FIFO。当事件被触发并经过优先级仲裁(例如,同时发生的多个事件,低通道号优先)后,它会被放入其映射的特定事件队列的尾部。
队列与传输控制器的映射: 这是理解EDMA3性能调优的关键。EDMA3 CC内部可以有一个或多个传输控制器(TC),每个TC是一个独立的数据搬运引擎。默认情况下,存在一个一一映射关系:队列0(Q0)的服务对象是TC0,队列1(Q1)对应TC1,以此类推。这意味着,放入Q0的事件,其产生的TR最终会由TC0来执行。
通道到队列的映射编程: 每个DMA通道和QDMA通道都可以独立地编程,决定其事件被放入哪个队列。这是通过DMAQNUMn(针对DMA通道)和QDMANUM(针对QDMA通道)寄存器实现的。这项配置是优化EDMA3性能、满足实时性截止时间的最重要手段之一。例如,你可以将高实时性、小数据量的音频收发通道映射到Q0/TC0,将低实时性、大数据量的图像搬运通道映射到Q1/TC1,从而实现资源隔离和优先级保障。
出队优先级: 当多个队列中都有事件等待处理,且它们对应的TC都就绪时,EDMA3 CC会优先从编号小的队列中取出事件进行处理。即Q0的优先级高于Q1,Q1高于Q2。但请注意一个关键例外:如果高优先级队列(如Q0)对应的TC(TC0)正忙于处理之前的TR而处于“忙”状态,而低优先级队列(如Q1)对应的TC(TC1)处于空闲状态,那么Q1中的事件会被优先出队并提交给TC1。这避免了高优先级队列阻塞低优先级队列的资源,是一种防止“饿死”的公平性设计。
队列旁路机制: 这是一个容易忽略但影响性能的细节。如果一个事件准备入队时,它目标队列和对应的TC都恰好是空的,那么这个事件会绕过队列,直接进入参数处理逻辑并提交给TC。这个事件不会被记录在队列状态寄存器中。这减少了事件处理的延迟,对于极低延迟的应用场景是利好,但在调试时,如果你完全依赖队列状态寄存器来追踪事件流,可能会发现事件“神秘消失”了。
3.2 队列的调试与资源跟踪
EDMA3提供了丰富的寄存器来窥视事件队列的内部状态,这对于调试复杂的实时数据流问题(通常是事后分析)极为有用。
队列状态寄存器(QSTATn): 这个寄存器提供了队列的实时快照。
STRTPTR(起始指针): 指向队列头部条目的偏移量。由于队列是环形FIFO,你需要用它来定位第一个有效事件。NUMVAL(有效条目数): 当前队列中等待处理的有效事件数量。结合STRTPTR,你可以遍历出所有在队列中的事件。WM(高水位标记): 记录自上次清零以来,该队列达到的最大NUMVAL值。这是评估队列深度配置是否合理的关键指标。
队列条目寄存器(QxEy): 通过QSTATn.STRTPTR和QSTATn.NUMVAL,你可以像读取数组一样读取Q0E0到Q0E15(对于Q0)等寄存器。这些寄存器告诉你每个条目对应的事件类型(外部触发、手动触发、链式触发、QDMA)和具体的事件号(通道号)。
实战应用: 假设你在调试一个视频处理流水线,发现某一帧数据偶尔丢失。你可以设置一个调试断点,在问题发生时检查相关队列的QSTATn。如果发现WM值经常达到15或16(队列满),并且NUMVAL值也很大,那很可能是事件产生速率持续高于TC处理速率,导致了事件丢失(会触发错误中断)。这时你就需要分析:是TC性能瓶颈(如访问慢速内存),还是事件映射不合理导致某个队列过载?
3.3 队列水位阈值与错误预防
为了防止因队列过载导致的事件丢失,EDMA3提供了可编程的水位阈值机制。通过配置队列水位阈值A寄存器(QWMTHRA),你可以为每个队列设置一个阈值(0-15)。
当队列中的有效事件数量(NUMVAL)超过这个阈值时,两件事会发生:
- 队列状态寄存器(
QSTATn)中的THRXCD位会被置位。 - 通道控制器错误寄存器(
CCERR)中对应的QTHRXCDn位会被置位。
更重要的是,第2点会触发EDMA3CC的错误中断。这为你提供了一个预警机制,而不是等到队列真正满了、事件丢失了才后知后觉。你可以在错误ISR中检查CCERR寄存器,如果发现是阈值超限错误,可以立即采取应对措施,如动态调整事件产生速率、提升相关任务的优先级��,从而避免数据丢失。
配置建议: 对于一个深度为16的队列,将阈值设置为12(75%负载)是一个比较合理的起点。这给了你一定的缓冲时间来响应预警。具体的阈值需要根据你的最坏情况事件到达率和TC处理时间来综合确定。
4. EDMA3传输控制器(TC)的内部运作与性能调优
事件队列调度好的传输请求(TR),最终会被提交给EDMA3传输控制器(TC)来执行实际的数据搬运。TC是EDMA3的“肌肉”,它的配置和运作方式直接决定了数据搬运的峰值带宽和效率。
4.1 TC的核心配置参数
每个TC在芯片设计时,其部分结构参数是固定的,但有一个关键参数可在软件中配置,深刻影响性能:
- FIFOSIZE: 数据FIFO的大小(字节)。这是TC内部用于暂存“飞行中”数据的缓冲区。读控制器从源地址读出的数据先放在这里,然后写控制器再从这里取出数据写入目标地址。更大的FIFO可以更好地缓冲数据,应对源/目标总线带宽不匹配或延迟波动。
- BUSWIDTH: 读/写控制器的数据总线宽度(字节)。这通常与芯片系统总线(如SCR)的宽度一致,决定了TC每次与互联总线交互的最大数据量。
- DSTREGDEPTH: 目标FIFO寄存器组的深度。这决定了TC可以流水线化处理的 outstanding TR 的最大数量,是实现高吞吐的关键。
- 默认突发大小(DBS):这是软件唯一可配置的关键性能参数。它决定了TC读/写控制器每次向总线发出的读/写命令的最大字节数(可配置为16、32或64字节)。DBS通过系统配置模块(SYSCFG)中的
CFGCHIP0寄存器进行设置。
DBS配置的权衡:
- 更大的DBS(如64字节): 能提高总线利用率,减少命令开销,在顺序访问大块连续内存时能获得更高的峰值带宽。
- 更小的DBS(如16字节): 在访问非对齐地址或小数据块传输时更灵活,可以减少因为对齐浪费的带宽,也可能降低单次传输的延迟。
- 手册强烈建议: DBS值应在系统初始化时根据应用需求静态设定,不建议在运行时动态修改。因为改变DBS会影响TC内部命令生成的逻辑,可能造成不可预知的行为。通常芯片的默认值已是经过权衡的优化值,如无充分理由和测试,不要轻易更改。
4.2 命令分片与地址对齐
TC并不会简单地将一个TR原样发给总线。它会根据DBS和TR参数(ACNT, BCNT),将大的传输请求分片成一系列符合DBS大小的总线突发命令。这个过程对性能有直接影响。
分片规则:
- 读/写控制器发出的每个命令大小 ≤ DBS。
- 对于一维传输(或优化后的二维传输),第一个命令的发出会使得后续命令的地址对齐到DBS边界。这是为了最大化总线效率。
看一个手册中的例子(DBS=32字节):
场景1:
ACNT=8, BCNT=8, SRCADDR=64, DSTADDR=191。- 读控制器: 发现
SRCBIDX=8等于ACNT,因此将二维传输优化为一维:等效ACNT=64, BCNT=1。源地址64是32字节对齐的。因此它发出两个32字节的命令(Cmd0: 32字节, Cmd1: 32字节),完美匹配。 - 写控制器: 目标地址191不对齐,且
DSTBIDX=10不等于ACNT,无法优化。因此它只能发出8个8字节的命令(Cmd0-Cmd7)。这里出现了性能瓶颈:读侧效率很高,但写侧因为地址不对齐和索引不匹配,产生了大量小命令,严重限制了整体吞吐量。
- 读控制器: 发现
场景2:
ACNT=64, BCNT=1, SRCADDR=31, DSTADDR=513。- 源地址31和目标地址513均不对齐32字节边界。
- 读控制器: Cmd0读1字节(使地址对齐到32),Cmd1读32字节,Cmd2读31字节。
- 写控制器: Cmd0写31字节(使地址对齐到32),Cmd1写32字节,Cmd2写1字节。
实战经验: 为了获得最佳EDMA3性能,应尽量保证源和目标地址按照DBS值(通常是32字节)对齐,并且ACNT最好是DBS的整数倍。在分配内存缓冲区时(尤其是用于EDMA3传输的缓冲区),使用对齐的内存分配函数(如malloc后手动对齐,或使用memalign)。地址不对齐会导致命令分片碎片化,显著降低有效带宽。
4.3 传输请求(TR)流水线与数据排序
DSTREGDEPTH参数(通常为4)启用了TC的一项强大功能:TR流水线。这意味着TC的读控制器可以提前处理后续的TR,而写控制器还在处理前一个TR的数据。
工作流程: 假设DSTREGDEPTH=4。
- TR0被提交给TC。
- TC读控制器开始为TR0发出读命令。读回的数据存入数据FIFO。
- 当TR0的读命令全部发出后,即使TR0的数据还未全部写完,读控制器就可以立即开始处理TR1的读命令。
- TR0和TR1的读数据可能乱序返回(TR1的数据先于TR0到达数据FIFO),但TC的写控制器会严格按照TR提交的顺序(TR0先于TR1)来发出写命令。数据排序在目标FIFO寄存器组中得到保证。
优势: 流水线化极大地消除了连续小TR之间的“读延迟气泡”。在图像处理中,连续搬运多个行缓冲区时,流水线可以几乎让读操作连续不断,从而显著提升整体吞吐量。
调试关注点: TC状态寄存器(TCSTAT)中的DSTACTV字段指示了当前目标FIFO寄存器组中有多少个有效的TR。结合DFSTRTPTR(目标FIFO起始指针),可以在调试时了解TC的流水线深度和忙碌状态。如果DSTACTV长期等于DSTREGDEPTH,说明TC的写端口可能成为瓶颈(例如,目标内存带宽不足或延迟太高)。
5. 从事件到完成:EDMA3全数据流梳理
现在,让我们把中断、队列、TC的所有知识串联起来,俯瞰一个事件在EDMA3中完整的生命周期。这能帮助我们建立起全局观,在调试时能快速定位问题环节。
步骤1: 事件触发与锁存外部外设(如McASP的接收寄存器满)产生一个事件信号,该信号被锁存到DMA事件寄存器(ER)的对应位(例如ER.E5)。对于手动触发、链式触发或QDMA触发,事件则分别锁存到ESR、CER或QER寄存器。
步骤2: 事件优先级仲裁与入队事件优先化逻辑对所有已锁存的事件进行仲裁。规则是:DMA事件优先级高于QDMA事件;同类型事件中,低通道号优先级高。胜出的事件根据其通道的DMAQNUM配置,被放入相应事件队列(如Q2)的尾部。同时,该事件在ER中的标志位会被复制到队列置位寄存器(SER)中,告知逻辑“此事件已入队,无需再次处理”。如果目标队列和对应TC都为空,事件则旁路队列,直接进入步骤3。
步骤3: 参数处理与传输请求生成当事件在队列中到达队首,且对应TC就绪时,它被出队。EDMA3 CC根据该事件对应的通道号,找到其参数集(PaRAM),开始处理。CC会检查这是否为一个“空”或“虚拟”传输。如果不是,则根据PaRAM中的源/目标地址、传输维度(ACNT, BCNT, CCNT)、索引等参数,组装成一个传输请求包(TRP)。
步骤4: 中断预触发(早期完成)如果PaRAM中配置了早期完成中断(OPT.TCINTEN或OPT.ITCINTEN),在TR被提交给TC之前,CC就会根据PaRAM中配置的TCC值,设置对应的IPR位。这允许CPU在数据传输实际开始前就得到通知,可以极快地启动后续处理(例如,准备下一个缓冲区)。
步骤5: TR提交与TC执行CC将TRP提交给对应的TC(例如Q2对应TC2)。TC接收TR后,将其存入程序寄存器组,然后传递到源激活寄存器组和目标FIFO寄存器组。读控制器开始根据TR分片发出读命令,数据流入数据FIFO。写控制器在数据可用时开始发出写命令。整个过程可能发生TR流水线。
步骤6: 传输完成与中断触发(正常完成)当TC完成所有数据的写入,并从目标端收到最终确认后,它会向CC返回一个完成状态。如果配置的是正常完成中断,CC此时才会根据TCC值设置IPR位。如果该TCC���IER中被使能,且DRAE权限正确,则一个完成中断脉冲将发送给CPU。
步骤7: CPU响应与清理CPU跳转到中断服务程序(ISR)。ISR读取IPR,判断是哪个TCC触发的中断,执行相应的数据处理或启动下一次传输。最后,向中断清除寄存器(ICR)的对应位写1,清除IPR中的挂起位。只有当一个影子区域的所有IPR位都被清除后,CC才会为新的完成事件产生新的中断脉冲。
6. 优先级体系全景与系统级调优
在复杂的多事件并发场景中,EDMA3内部有一套完整的优先级仲裁体系,理解它对于设计满足实时性要求的系统至关重要。优先级从高到低,在不同环节起作用:
1. 通道优先级(同时触发的事件): 当多个DMA(或QDMA)事件在同一时刻发生时,通道号更小的事件拥有更高优先级(DMA通道0最高,31最低;QDMA通道0最高,7最低)。此外,DMA事件的优先级总是高于QDMA事件。这个优先级仅在事件初始提交到队列时起作用。
2. 触发源优先级(同一通道的多重触发): 如果一个DMA通道同时被事件触发、手动触发和链式触发置位,它们的服务顺序是:事件触发(ER) > 链式触发(CER) > 手动触发(ESR)。这确保了外部实时事件能得到最及时的响应。
3. 出队优先级(队列间调度): 当多个队列中都有事件等待,且它们对应的TC都空闲时,编号小的队列优先级更高(Q0 > Q1 > Q2 ...)。这给了我们一个强大的工具:将最高实时性要求的通道映射到低编号队列。
4. 传输控制器(TC)主设备优先级: 这是系统级的优先级,影响力远超前面的内部优先级。在SoC互联总线上,EDMA3的每个TC都是一个主设备,与其他主设备(如CPU、其他DMA)竞争总线带宽。这个优先级在系统配置模块(SYSCFG)的MSTPRI寄存器中配置(0最高,7最低)。
调优实战: 假设一个音频视频系统:
- 音频RX/TX(高实时性,小数据量): 映射到Q0。将TC0的主设备优先级设为较高(如1)。
- 摄像头输入(高带宽,中等实时性): 映射到Q1。将TC1的主设备优先级设为中等(如3)。
- 显示输出(高带宽,但可容忍一定延迟): 映射到Q2。将TC2的主设备优先级设为较低(如5)。
- 内存间大数据块拷贝(后台任务): 使用QDMA或映射到Q3,优先级最低。
同时,确保为高优先级TC所访问的存储器(如存放音频缓冲区的片上RAM)配置更低的访问延迟。通过这种队列映射 + 主设备优先级 + 存储器分区的组合拳,才能构建出真正确定性的实时数据传输系统。调试时,如果发现某个高实时性通道偶尔超时,除了检查其本身配置,一定要从整个系统的角度,审视是否有低优先级但高带宽的TC(或CPU)正在霸占总线,阻塞了高优先级TC的访问。