EDMA3性能调优实战:从优先级仲裁到传输优化的嵌入式DMA进阶指南

发布时间:2026/7/21 7:52:13
EDMA3性能调优实战:从优先级仲裁到传输优化的嵌入式DMA进阶指南 1. 项目概述从“能用”到“好用”的EDMA3性能调优之路在嵌入式系统开发尤其是涉及音视频处理、高速数据采集或网络通信的项目里直接内存访问DMA技术是提升系统性能、保证实时性的关键。它就像一位不知疲倦的“搬运工”在CPU忙于计算时默默地在内存与外设之间搬运数据。然而很多开发者对DMA的认知往往停留在“配置好源地址、目的地址和长度触发后就不用管了”的层面。实际上要让这位“搬运工”发挥出最大效能尤其是在德州仪器TI的增强型直接内存访问EDMA3控制器这样功能强大的硬件上需要深入理解其内部工作机制和系统级的协同策略。我经历过不止一个项目初期DMA配置看似工作正常数据能搬但一到高负载或复杂场景系统就出现卡顿、丢帧甚至数据错误。排查下来问题往往不是DMA本身坏了而是优先级冲突、总线拥塞或传输模式低效导致的。EDMA3控制器远不止是一个简单的数据搬运通道它集成了通道控制器CC和多个传输控制器TC其性能表现与系统总线架构、外设实时性需求、数据传输模式紧密耦合。本文将聚焦于EDMA3控制器从“功能实现”到“性能优化”的实战进阶。我们将不满足于让DMA“跑起来”而是要让它“跑得又快又稳”。核心将围绕三个直接影响系统表现的关键维度展开首先是系统优先级仲裁如何为音频、视频等实时任务分配更高的总线“路权”避免被后台大数据搬运“堵车”其次是传输控制器TC的内部优化机制如何通过巧妙的参数设置诱使硬件将复杂的2D传输“折叠”成高效的1D传输大幅提升总线利用率最后是读命令节流Throttling如何给DMA这匹“快马”套上合适的缰绳防止它过快消耗总线资源而饿死其他高优先级主设备。理解并应用这些策略是构建高性能、高可靠嵌入式系统的必修课。2. 系统级性能考量优先级是实时性的生命线很多开发者容易忽略一个事实DMA控制器本身是系统总线上的一个“主设备”Master。这意味着当它发起数据传输时需要向系统互连如Switched Central Resource, SCR申请总线使用权。在同一时刻CPU、其他DMA控制器、高速外设如Display Subsystem可能都在竞争总线资源。如果所有请求者都以默认的最高优先级发起请求势必导致混乱和冲突实时性任务将无法得到保证。2.1 理解EDMA3的优先级架构EDMA3的优先级配置分为两个层次通道队列优先级和传输控制器TC系统优先级。通道队列优先级在EDMA3通道控制器CC内部管理。它决定了不同通道的传输请求TR被提交到TC的顺序。通常我们可以将实时音频通道分配到高优先级队列如Queue 0而将后台内存拷贝任务分配到低优先级队列如Queue 2。然而这仅仅是内部排队。更关键的是TC系统优先级它决定了当多个TC或TC与其他主设备同时向系统总线发起读写命令时谁先被服务。这是通过芯片级的寄存器通常位于系统控制模块为每个TC分配一个仲裁权重或优先级数值来实现的。2.2 实战配置策略与误区根据TI官方建议及我的实战经验优先级配置应遵循“业务驱动实时优先”的原则识别实时性外设首先梳理系统中所有使用EDMA3的外设。像音频接口McASP/I2S、视频采集VPIF、显示输出等通常有严格的时序和延迟要求属于硬实时或软实时任务。分配专用TC与高系统优先级为这些实时外设分配专用的传输控制器TC并将该TC的系统优先级设置为最高或较高。例如在一个多核DSP系统中你可以将TC0专门服务于McASP接收/发送并在系统优先级寄存器中将其权重设为7假设0为最高。后台任务降级处理将用于内存初始化、大块数据搬移如从外部DDR拷贝到内部L2 SRAM等无实时性要求的任务分配到另一个TC如TC1并将其系统优先级设置为较低。避免“默认即最高”的陷阱许多芯片的默认配置是所有TC优先级相同且为最高。这是一个危险的默认值。如果不加修改一个疯狂进行内存拷贝的后台TC可能会严重阻塞音频TC访问内存导致音频播放出现爆音或中断。实操心得优先级冲突的典型症状我曾调试一个音频播放同时进行SD卡日志写入的系统。音频偶尔会出现细微“咔哒”声。使用芯片的性能计数器Performance Counters监控总线访问延迟发现当SD卡DMA启动时音频DMA访问内存的延迟从几十个周期飙升到数百个周期。解决方案就是将SD卡DMA使用的TC优先级调低问题立即消失。工具推荐善用芯片提供的性能分析工具如TI的UIA、Sys/Bios System Analyzer监控总线负载和延迟是定位优先级问题的利器。2.3 配置示例与寄存器操作假设我们使用TI的C6000系列DSP其系统优先级可能在CP_INTC或System Module的相关寄存器中配置。以下是一个概念性的代码片段展示如何设置TC优先级// 假设 TC0 用于高优先级音频TC1 用于低优先级内存拷贝 // 查找芯片数据手册中系统优先级控制寄存器的地址 volatile uint32_t *sys_priority_reg (volatile uint32_t *)0x01840000; // 读取当前值 uint32_t reg_val *sys_priority_reg; // 设置优先级假设字段 TC0_PRI [1:0], TC1_PRI [3:2]值越小优先级越高 reg_val ~(0x3 0); // 清零TC0优先级字段 reg_val | (0x0 0); // 设置TC0优先级为0最高 reg_val ~(0x3 2); // 清零TC1优先级字段 reg_val | (0x2 2); // 设置TC1优先级为2较低 // 写回寄存器 *sys_priority_reg reg_val;关键检查点配置完成后务必确认高优先级TC关联的通道是否正确映射。在系统初始化早期完成此配置避免运行时动态修改引发不可预知的行为。3. 传输控制器TC的魔法化繁为简的传输优化EDMA3的传输控制器TC并非机械地执行参数集PaRAM定义的传输它内置了智能优化逻辑。在特定条件下它能将一个二维2D传输请求在内部“重新打包”成一个一维1D传输从而显著减少总线命令的发布次数提升总线利用率和整体吞吐量。理解并利用这个特性是进行高性能DMA编程的关键。3.1 优化触发的“黄金五条”TC对2D传输进行1D优化的条件非常具体必须同时满足以下五点缺一不可ACNT ≤ DBS (Destination Burst Size)第一维的字节数ACNT必须小于或等于目的端口的突发Burst大小。DBS是硬件属性通常与总线位宽和内存类型相关例如对于64位DDR接口DBS可能是8字节。这是优化的物理基础确保优化后的长数据块仍能有效利用突发传输。ACNT 是2的幂ACNT的值必须是2的幂如1, 2, 4, 8, 16, 32, ...。这有利于地址对齐和内部缓冲管理。BIDX ACNT源和目的地址的B维索引SRCBIDX 和 DSTBIDX必须等于ACNT。这意味着在2D传输中每个“行”A维结束后地址的跳变正好是ACNT字节数据在内存中是连续排列的。BCNT ≤ 1023第二维的计数BCNT不能超过1023。这是一个硬件限制。SAM/DAM 0 (增量模式)源地址和目的地址的修改模式必须是增量模式Increment而不是恒定或索引模式。当以上条件全部满足时TC内部会执行一个转换它将原本的ACNT * BCNT次传输每次ACNT字节合并视为一次ACNT ACNT * BCNT字节的1D传输其中BCNT 1。3.2 优化效果对比场景A vs. 场景B让我们用文档中的例子来量化感受优化带来的巨大差异场景A非优化需要传输4096字节连续数据。配置为ACNT 4字节BCNT 1024。TC视角这是一个2D传输有1024个“行”每行4字节。总线操作由于BCNT1024 1023不满足优化条件。TC将向总线发布1024次读命令和1024次写命令每次命令只传输4字节。这是极其低效的无法利用总线的突发传输能力总线利用率极低。场景B优化同样传输4096字节连续数据。配置为ACNT 64字节BCNT 64。检查条件ACNT64假设DBS64条件1满足。64是2的幂条件2满足。设置SRCBIDX DSTBIDX 64条件3满足。BCNT64 ≤ 1023条件4满足。设置SAMDAM0条件5满足。TC视角所有条件满足TC内部将其优化为一个1D传输ACNT 64 * 64 4096字节BCNT 1。总线操作TC会尝试发布一次或少数几次大尺寸的突发读/写命令例如一个4096字节的突发或拆分成多个符合总线最大突发长度的命令。这能最大化总线带宽利用率吞吐量可能是场景A的数十倍。3.3 实战编程指南与参数计算如何在编程中主动设计以满足优化条件关键在于数据布局的规划和参数的计算。案例摄像头图像行数据拷贝假设摄像头输出一帧图像为1280x720每个像素16位2字节。数据按行连续存储。我们需要将一帧数据从采集缓冲区搬运到处理缓冲区。目标将Src[1280*720*2]连续数据块搬运到Dst。初级配置可能低效ACNT 2(一个像素)BCNT 1280*720 921600SRCBIDX DSTBIDX 2分析BCNT远超1023无法优化。TC将发起92万次2字节的小传输性能灾难。优化配置利用2D优化将一帧视为720行每行1280像素。ACNT 1280 * 2 2560字节一行数据BCNT 720行数SRCBIDX DSTBIDX 2560行间距SAM DAM 0增量分析ACNT2560需确认DBS通常为128或256字节。2560 DBS条件1不满足仍然无法触发1D优化。高级优化配置结合循环和链接既然单行2560字节可能超过DBS我们可以进一步拆分。假设DBS256字节。将一行数据2560字节分成10个连续的块每块256字节。第一级传输行内块搬运ACNT 256(满足 ≤ DBS)BCNT 10SRCBIDX DSTBIDX 256BCNTRLD 10(为链接做准备)LINK指向下一个参数集用于跳转到下一行。检查ACNT256(2的幂)BIDX256BCNT10≤1023SAM/DAM0。全部满足触发优化TC会将这10个256字节的块视为一个2560字节的1D传输。第二级传输行间链接通过链接Linking功能在完成一行10块传输后自动加载下一个参数集。下一个参数集中SRC和DST地址增加一行的大小2560字节其他参数不变继续传输下一行。这样通过一次触发就能高效完成整帧数据的搬运。避坑指南参数计算的常见错误忽略DBS盲目设置ACNT为很大值以为能获得更大突发殊不知若ACNT DBS优化直接失效。务必查阅芯片手册确定目标内存端口的DBS值。混淆BIDX和CIDX在2D传输中BIDX是同一“帧”内不同“行”之间的地址偏移。如果你要做3D传输例如多个帧CIDX才是帧间的偏移。设置错误会导致数据错位。忘记设置SYNCDIM2D传输必须将OPT寄存器中的SYNCDIM位设置为1AB同步否则传输将以A同步进行BCNT参数不起作用优化更无从谈起。静态参数集如果希望传输完成后自动链接到新参数集进行下一次传输如Ping-Pong缓冲务必确保当前参数集的STATIC位为0动态否则参数不会被更新。4. 读命令节流RDRATE给快马套上缰绳EDMA3的传输控制器TC在默认情况下会以尽可能快的速度发布读命令从源地址读取数据。这在追求最大吞吐量的场景下是好事。但在复杂的多主设备系统中这可能成为一个问题一个高带宽、低优先级的DMA传输如内存初始化可能会瞬间占满某个从设备如共享的DDR内存控制器的命令队列导致更高优先级的设备如CPU取指、显示控制器的访问请求被阻塞产生严重的实时性延迟。4.1 RDRATE的工作原理RDRATE寄存器正是为了解决这个问题而设计的。它不是一个开关而是一个“节流阀”。其值定义了TC的读控制器在为一个传输请求TR发布两次连续的读命令之间需要插入的等待周期数。RDRATE 0默认值。不节流读命令以最快速度背靠背back-to-back发布。RDRATE N每发布一个读命令后等待N个时钟周期再发布下一个读命令。这个机制有效地降低了TC读接口的“攻击性”为其他主设备让出了总线访问机会。需要注意的是节流只作用于读命令写命令由于其特性必须伴随数据天然存在间隔通常无需额外节流。4.2 配置策略与场景分析如何设置RDRATE的值没有放之四海而皆准的公式但可以遵循以下原则高优先级、实时性TC服务于音频、关键传感器数据采集的TC。建议保持RDRATE为0或设置一个很小的值如1-2。目标是最大化其吞吐量确保数据及时搬运避免缓冲区上溢/下溢。低优先级、后台TC用于非关键性大数据块搬移、内存初始化的TC。应设置一个较大的RDRATE值如8-16甚至更高。这能显著降低其对总线资源的占用率将带宽“谦让”给高优先级任务。混合负载TC如果一个TC需要服务多种优先级的通道情况变得复杂。更优的架构设计是根据业务优先级将通道分配到不同的TC并为每个TC设置独立的RDRATE。如果硬件资源有限只能共用TC那么RDRATE的设置需要妥协并可能需要结合更精细的通道优先级Queue Priority来控制。4.3 实战配置与性能权衡配置RDRATE通常在EDMA3 TC的全局配置寄存器中。以下是一个概念性示例// 假设 TC0 用于高优先级音频TC1 用于低优先级后台拷贝 volatile uint32_t *tc0_base (volatile uint32_t *)EDMA3_TC0_BASE; volatile uint32_t *tc1_base (volatile uint32_t *)EDMA3_TC1_BASE; // 设置 TC0 读命令速率最小延迟最高优先级 *(tc0_base RDRATE_OFFSET) 0; // 或 1 // 设置 TC1 读命令速率主动节流降低总线占用 *(tc1_base RDRATE_OFFSET) 8; // 插入8个周期延迟性能权衡的思 增加RDRATE必然会降低该TC的峰值读带宽。例如如果总线时钟为200MHz发布一个读命令本身需要1个周期那么RDRATE0时理论最大读命令率约为200M commands/s。RDRATE8时命令间隔至少9个周期理论最大读命令率降至约22.2M commands/s。这并不意味着实际传输带宽会成比例下降因为带宽还受限于内存延迟、数据总线宽度等因素。但节流确实引入了可控的延迟。关键是要通过系统级性能分析如使用仿真器或性能计数器来验证在引入节流后低优先级任务的完成时间是否仍在可接受范围内同时高优先级任务的延迟抖动是否得到了显著改善。调试经验识别总线拥塞总线拥塞的症状往往是“时好时坏”的性能抖动和高延迟。除了使用专业性能分析工具一个简单的软件方法是在高低优先级任务中插入时间戳。观察低优先级DMA传输期间高优先级任务如音频中断服务例程的执行时间是否显著增加。如果增加很可能发生了总线竞争。此时调整低优先级TC的RDRATE是一个有效的缓解手段。5. 复位、时钟与低功耗管理稳定性的基石性能优化建立在系统稳定工作的基础上。EDMA3控制器的初始化、时钟和功耗管理若处理不当会导致数据错误、传输挂起甚至系统死机。5.1 复位后的初始化序列芯片上电或硬件复位后EDMA3控制器及其配置寄存器会被复位但参数存储器PaRAM的内容是未定义的。这是一个关键陷阱。错误做法假设PaRAM在上电后是全零或某个已知状态直接配置通道并启用事件。正确做法在启用任何DMA通道之前必须首先初始化所有计划使用的PaRAM集合Parameter Set包括链接参数。即使你打算在运行时动态修改它们也需要一个确定的初始值。// 安全的初始化步骤 1. 禁用EDMA3CC全局控制寄存器中禁用。 2. 初始化所有要用到的PaRAM Set写OPT, SRC, DST, CNT, IDX等寄存器。对于不立即使用的Set可以写为已知安全值如将OPT设为0x00000000即禁用状态。 3. 配置事件队列映射、通道优先级等CC全局设置。 4. 配置TC相关设置如RDRATE。 5. 启用EDMA3CC。 6. 按需启用具体通道的事件设置EER寄存器相应位。5.2 时钟与低功耗模式下的安全操作EDMA3的时钟通常由PLL提供。在进入低功耗模式如DSP核休眠时需要谨慎管理EDMA3的状态。核心原则在请求停止EDMA3时钟通过PSC模块之前必须确保控制器内部没有任何待处理的活动。安全关闭序列软件层面停止禁用所有DMA/QDMA通道的事件使能清除EER。等待所有已提交的事件被处理完成队列为空。可以通过查询EDMA3CC的CCSTAT寄存器来确认无挂起事件、事件队列为空、传输请求处理逻辑空闲、无完成中断请求。对于每个EDMA3TC查询其TCSTAT寄存器确认读写控制器空闲无正在处理的传输请求TR。硬件层面关断通过PSC模块先请求禁用EDMA3CC的时钟。再请求禁用各个EDMA3TC的时钟。外设联动关闭如果EDMA3正在服务某个外设如McBSP而你需要同时关闭两者顺序至关重要先禁用外设停止其产生事件。再禁用服务此外设的DMA通道清除EER。然后按照上述步骤1和2禁用EDMA3CC和TC。最后通过PSC关闭外设的时钟。唤醒恢复从低功耗模式唤醒后在重新启用EDMA3和外设前最好重新初始化相关的PaRAM和配置寄存器因为某些深度休眠模式可能导致寄存器内容丢失。血泪教训不完整的关闭导致的死锁我曾遇到一个系统在尝试进入低功耗模式时卡死。调试发现在禁用DMA通道事件后立即通过PSC请求关闭EDMA3时钟。但此时TC内部还有一个未完成的传输请求可能是之前提交的TCSTAT显示忙。由于时钟即将被关闭TC无法完成该请求而PSC又在等待TC空闲的确认导致死锁。解决方案就是在禁用事件后增加一个等待循环持续查询CCSTAT和TCSTAT直到所有控制器都报告空闲状态再进行时钟停止操作。这段等待代码对于系统稳定性至关重要。6. 仿真与调试考量让问题在实验室浮现在仿真器Emulator环境下调试带EDMA3的系统其行为与全速运行时有细微差别理解这些差别能避免误判。6.1 仿真暂停时的EDMA3行为当你在集成开发环境如CCS中设置断点、单步执行或暂停CPU时EDMA3控制器并不会随之暂停。它会继续运行继续锁存和处理事件继续提交和执行传输请求。这意味着数据可能在你暂停时被搬运你设断点查看的某个内存缓冲区可能在断点触发后瞬间被DMA修改导致你看到的数据不是“当时”的数据。外设交互可能不同步EDMA3的行为与其服务的外设强相关。如果外设在仿真暂停时有特殊行为如某些外设可配置为在仿真暂停时停止生成事件那么EDMA3的响应也会不同。例如McBSP如果配置为FREE0且SOFT0/1在仿真暂停时会停止生成REVT/XEVT事件与之关联的DMA传输也会停止。但一个定时器Timer外设可能不受仿真暂停影响继续定期产生事件并触发DMA。6.2 调试策略与工具使用使用“读-写”观察点代替断点如果你关心某个特定内存地址的数据何时被DMA写入不要在该地址设代码断点这会暂停CPU但DMA可能继续写。应该使用内存观察点Watchpoint设置为当该地址被写入时触发。这样可以在不停止CPU和DMA的情况下捕获访问事件并通过日志或实时变量查看上下文。善用EDMA3的调试寄存器EDMA3提供了丰富的状态寄存器如CCSTAT、TCSTAT、事件寄存器ER/EER/ECR、完成中断寄存器IPR等。在调试时可以定期或在关键点读取这些寄存器了解事件队列深度、TC忙闲状态、中断 pending 情况。隔离测试当怀疑DMA传输有问题时构建一个最小测试用例用软件手动触发一个DMA传输写ESR寄存器而不是依赖外设事件。这样可以排除外设配置错误或事件生成问题的干扰聚焦于DMA参数配置本身。逻辑分析仪与系统跟踪对于复杂的时序问题或性能分析芯片上的系统跟踪模块如TI的System Trace或外部逻辑分析仪抓取EDMA3事件信号是终极武器。它们可以非侵入式地记录事件触发、传输开始/结束的精确时间戳是分析实时性和排查偶发故障的利器。7. 从理论到实践典型用例的深度参数解析理解了优化原理和系统考量后我们通过几个典型用例深入剖析其PaRAM配置的每一个细节看看如何将理论应用于实践。7.1 用例一高效的内存块搬移Block Move这是最基础的操作但优化与否性能差异巨大。场景将256字节数据从外部内存0x4000_0000搬移到内部L2 SRAM0x1180_0000。数据在源和目的都是连续存放的。初级配置A同步1D视角ACNT 256(总字节数)BCNT 1SYNCDIM 0(A同步)SRCBIDX DSTBIDX 0分析这是一个简单的1D传输。如果ACNT256且是2的幂且≤ DBSTC可能会将其优化为一个256字节的突发传输。这已经不错。更优的2D配置诱优化 假设我们已知DBS128字节。为了最大化总线效率我们可以尝试诱导TC进行1D优化。ACNT 128(等于DBS是2的幂)BCNT 2(256 / 128)SYNCDIM 1(AB同步因为BCNT1)SRCBIDX DSTBIDX 128(等于ACNT)检查优化条件ACNT(128) ≤ DBS(128) -满足ACNT是2的幂(128) -满足BIDX ACNT (128) -满足BCNT(2) ≤ 1023 -满足SAM/DAM 0 -满足结果所有条件满足TC内部会将这个ACNT128, BCNT2的2D传输视为一个ACNT256, BCNT1的1D传输并尝试发出一个256字节的优化突发命令。这比配置成ACNT256, BCNT1的1D传输在TC内部处理上更符合其优化逻辑在某些架构上可能获得最佳性能。参数表解读 以文档中图16-16为例OPT寄存器中STATIC1表示传输完成后参数不更新无链接。SYNCDIM0但它的BCNT1所以本质上还是1D传输。LINK0xFFFF表示无效链接地址。7.2 用例二视频子帧提取Subframe Extraction这是一个经典的2D到1D的“采样”操作展示了EDMA3处理非连续数据的能力。场景从一幅640x480的16位灰度图像存储在SDRAM中提取一个16x12像素的子图像到L2 SRAM。源图像中子帧的起始位置为第10行、第100列以像素为单位。参数计算步骤确定数据布局源图像每行640像素 * 2字节 1280字节。子帧从第10行第100列开始。源起始地址 图像基址 (10 * 1280) (100 * 2)。目的需要一块连续内存存放16122384字节的子帧数据。规划传输维度将子帧的一行16像素作为传输的一个单元。ACNT 一行子帧的字节数 16 * 2 32字节。BCNT 子帧的行数 12。这是一个2D传输所以SYNCDIM1(AB同步)。计算地址索引源地址索引每传输完一行子帧ACNT字节源地址需要跳转到源图像中下一行子帧的起始位置。这个跳变是跳过源图像一行的剩余部分到达下一行的对应列。SRCBIDX 源图像一行的总字节数 - 子帧一行的字节数 源图像中到下一行同一列的偏移这里需要仔细计算。更准确的描述传输完一行(32字节)后源地址需要从当前行的第100列移动到下一行的第100列。所以需要跳过当前行剩下的 (640-16)2 字节再跳过下一行前面的 1002 字节不对。正确的SRCBIDX从当前行子帧结尾到下一行子帧开头在内存中的字节偏移。即SRCBIDX 源图像一行字节数 1280。因为源数据是连续的二维数组我们每次读一行中的一段读完这一段的结尾地址自然指向下一行紧接着的位置但我们需要的是下一行子帧开头的位置。所以需要跳过的偏移是1280 - 32 0等等这里文档例子中SRCBIDX0x05001280。这说明它的源数据子帧的每一行在内存中是连续排列的这不符合通常的图像存储。文档图16-17显示源是一个大矩形子帧是从中抠出的一个小矩形。如果SRCBIDX1280意味着每次读完后源地址直接跳到下一行对应列的位置。这要求源图像中子帧的每一行数据在内存中必须是连续的即子帧区域在源图像中本身就是一个连续的矩形块。这通常需要源图像的子帧起始列是0。如果起始列不是0SRCBIDX需要是1280但源起始地址需要精确计算到子帧左上角像素。简化理解针对文档例子它假设子帧就是从图像左上角开始抠的。所以SRCBIDX就是源图像的行宽1280字节。目的地址索引目的内存是连续的。每写完一行子帧数据32字节目的地址只需简单递增到下一行开头。DSTBIDX 子帧一行的字节数 32字节。文档参数验证查看图16-18ACNT0x002032,BCNT0x000C12,SRCBIDX0x05001280,DSTBIDX0x002032。SYNCDIM1。这证实了我们的计算。OPT中STATIC1因为这只是单次提取。关键启发这个用例的精髓在于利用SRCBIDX和DSTBIDX的不同实现了从大数组中间隔采样到连续小数组的转换。SRCBIDX很大实现了“跨行”读取DSTBIDX很小实现了“连续”写入。这是EDMA3进行数据重排的经典应用。7.3 用例三多数组交织排序Data Sorting这个例子更复杂展示了EDMA3如何通过3D传输和自链接Chaining实现强大的数据重组功能。场景有多个数据数组例如A, B, C, D四个数组每个数组1024个4字节元素它们在源内存中是分开连续存储的A全部然后是B全部...但我们需要在目的内存中变成交织存储A[0], B[0], C[0], D[0], A[1], B[1]...。思维转换把源数据想象成一个[CCNT][BCNT][ACNT]的3D立方体。ACNT 一个元素的字节数 4。BCNT 每次排序的数组数量 4(A,B,C,D)。CCNT 每个数组的元素个数 1024。传输的“步进”逻辑最内层A维每次传输ACNT4字节即一个元素。传输后源和目的地址都增加4SRCBIDXDSTBIDX4先别急。中间层B维传输完一个数组的一个元素后要切换到下一个数组的同一个位置的元素。源地址需要从A[0]跳到B[0]。由于A、B、C、D在源内存是分开存放的B[0]的地址相对于A[0]的偏移是ACNT * BCNT不对应该是ACNT * CCNT让我们理清源内存布局是A[0], A[1], ... A[1023], B[0], B[1], ...。所以从A[0]到B[0]需要跳过整个A数组即ACNT * CCNT 4 * 1024 4096字节。但这是在B维内步进吗不B维是在同一个“帧”内不同数组间切换。所以SRCBIDX应该等于ACNT * CCNT 4096。目的地址我们希望交织存储所以写完A[0]后目的地址应该指向B[0]的位置它紧挨着A[0]所以DSTBIDX ACNT 4。最外层C维当完成一组4个数组的当前元素即A[i], B[i], C[i], D[i]的传输后要开始传输下一组元素A[i1], B[i1]...。源地址从D[i]跳到A[i1]。A[i1]就在A[i]后面所以源地址在C维的索引SRCCIDX就是ACNT 4。目的地址从交织块的D[i]位置跳到下一个交织块的A[i1]位置。一个完整的交织块大小是ACNT * BCNT 4*416字节。所以DSTCIDX ACNT * BCNT 16。参数总结ACNT 4BCNT 4CCNT 1024SRCBIDX ACNT * CCNT 4 * 1024 4096 (0x1000)DSTBIDX ACNT 4SRCCIDX ACNT 4DSTCIDX ACNT * BCNT 16 (0x10)SYNCDIM 1(AB同步因为BCNT1且这是3D传输的基础)自链接实现连续排序 一次触发只能完成BCNT4个数组的一个元素的排序。要完成所有1024个元素的排序需要触发1024次。这可以通过通道自链接Chaining实现在参数集中设置LINK地址指向自己并配置TCC传输完成码来在每次传输完成C维计数减为0时触发一个“中间完成”事件这个事件可以链式触发同一个通道再次启动。同时需要将STATIC位设为0并正确设置BCNTRLD以便在每次C维迭代后重载BCNT计数器。文档图16-20中的参数LINK0xFFFF无效和STATIC0可能只是为了展示单次传输的参数计算。在实际实现自链接排序时需要配置有效的LINK地址和TCC。这个用例深刻体现了EDMA3参数集的强大和灵活。通过精心设计ACNT、BCNT、CCNT以及各个索引可以实现极其复杂的数据模式变换将CPU从繁琐的数据重排任务中彻底解放出来。