TMS320C6670嵌入式DSP开发:PASS PLL时钟与EDMA3控制器配置详解
1. 项目概述与核心价值
在嵌入式DSP系统开发,尤其是像TI TMS320C6670这样的高性能多核SoC平台上,有两项底层配置是决定系统成败的基石:一是为整个芯片提供“心跳”的时钟系统,二是确保数据在芯片内部高速流动的“血管”——DMA控制器。很多工程师在项目初期,往往把精力集中在算法实现和任务调度上,却容易忽视这些底层硬件的正确配置,结果就是系统要么根本跑不起来,要么性能远低于预期,稳定性也差。我见过不止一个项目,因为PLL配置不当导致芯片发热异常,或者因为EDMA参数设置错误,数据吞吐量连理论值的十分之一都达不到,最后不得不返工,耗时耗力。
今天,我们就来深入拆解TMS320C6670这颗芯片里两个至关重要的模块:PASS PLL和EDMA3控制器。PASS PLL负责为网络协处理器(Packet Accelerator Subsystem)等关键外设提供精准时钟,它的配置直接关系到相关模块能否正常工作以及工作频率是否达标。而EDMA3控制器,作为C6670上功能最强大的数据搬运引擎,其配置的优劣直接决定了多核间数据交换、外设数据搬移的效率,是释放C66x内核强大计算能力的关键。本文的目标,就是让你不仅知道这两个模块的寄存器怎么填,更要理解每个配置项背后的设计意图、参数计算的逻辑,以及在实际工程中可能遇到的“坑”和应对技巧。无论你是正在评估C6670平台,还是已经深陷调试泥潭,希望这篇结合了手册解读和实战经验的总结能给你带来实实在在的帮助。
2. PASS PLL:为网络协处理器提供精准时钟
在C6670 SoC中,PLL(锁相环)不止一个。除了为CPU核心提供时钟的主PLL(Main PLL)外,还有专门为特定子系统服务的PLL,PASS PLL就是其中之一。它的输出(PLLOUT)经过一个固定的3分频后,直接馈送给网络协处理器(Network Coprocessor)。这意味着,网络协处理器的工作时钟完全依赖于PASS PLL的稳定输出。
2.1 PASS PLL的工作原理与复位特性
PLL本质上是一个反馈控制系统,它通过比较参考时钟和反馈时钟的相位差,调整内部压控振荡器(VCO)的频率,最终输出一个频率稳定、且与参考时钟保持严格相位关系的时钟信号。在C6670中,PASS PLL的参考时钟通常来源于芯片的某个外部晶振或时钟输入,经过主PLL和PLL控制器分频后得到。
手册中特别强调了一点:PASS PLL受上电复位影响。这意味着,只有在芯片彻底断电再上电的“冷启动”过程中,PLL的内部时钟才会被复位并经历一个失锁到重新锁定的过程。在其他的热复位或软件复位中,PASS PLL会保持锁定状态。这个特性很重要,它告诉我们,PASS PLL的初始化配置代码,通常只需要在系统上电初始化阶段执行一次。当RESETSTAT引脚变为高电平时,PLL应该已经完成锁定,软件可以安全地切换时钟源。
注意:虽然手册说其他复位不会导致失锁,但在实际调试中,如果发现网络协处理器工作异常,在排查软件问题时,也可以将PASS PLL的重新初始化作为一个备选的“硬重启”手段,有时能解决一些棘手的、状态机卡死的问题。
2.2 寄存器详解与初始化序列
PASS PLL的配置主要通过两个寄存器完成:PASSPLLCTL0和PASSPLLCTL1。手册给出的初始化序列是标准操作流程,我们必须严格遵守,否则可能导致PLL无法锁定或输出时钟不稳定。
1. 关键寄存器位域解析
在动手配置前,必须理解每个关键位的作用:
PASSPLLCTL0寄存器:
BYPASS (位23):旁路模式使能。置1时,PLL被旁路,参考时钟直接输出。这在PLL配置和锁定过程中是必要的安全步骤。PLLM[12:0] (位18-6):13位的乘法器(Multiplier)。这是决定输出频率最关键的参数之一。PLL的输出频率Fout与输入参考频率Fref的关系为:Fout = (PLLM + 1) * Fref / (PLLD + 1)。PLLM的值需要根据所需的输出频率和输入频率计算。PLLD[5:0] (位5-0):6位的参考时钟分频器(Divider)。用于降低输入到PLL频率检测电路的参考时钟频率,通常用于满足PLL对输入频率范围的要求。BWADJ[7:0] (位31-24):带宽调整值(低8位)。这个参数与PLL的环路滤波器带宽有关,影响锁定的速度和稳定性。
PASSPLLCTL1寄存器:
PLLRST (位14):PLL复位位。置1将复位PLL内部逻辑,通常在配置新的M和D值前使用。PLLSELECT (位13):PLL选择位。对于PASS PLL,此位必须设置为1,以选择PLL的输出作为PASS模块的时钟源。ENSAT (位6):必须设置为1,以确保PLL工作在最佳状态。具体功能与内部锁相环的饱和模式有关,按手册要求设置即可。BWADJ[11:8] (位3-0):带宽调整值(高4位)。与PASSPLLCTL0中的低8位共同组成12位的BWADJ值。
2. 初始化序列步骤精讲
手册给出的10步序列是黄金标准,我们来一步步拆解其背后的原因:
- 设置ENSAT=1:这是准备工作,确保后续PLL操作在一个优化的内部状态下进行。
- 设置BYPASS=1:这是关键的安全步骤。在重新配置PLL参数前,先将时钟路径切换到旁路模式(即直接使用参考时钟)。这样可以避免在PLL频率变化过程中,给下游逻辑送去一个频率剧烈抖动的时钟,导致系统崩溃。
- 设置PLLRST=1:复位PLL。在改变M和D值之前,需要将PLL置于一个确定的初始状态。
- 配置PLLM和PLLD:根据目标频率计算并写入这两个值。这里有个大坑:计算时务必确认你使用的参考时钟频率
Fref是经过主PLL和PLL控制器分频后的实际输入到PASS PLL的频率,而不是外部晶振频率。同时,要确保计算出的VCO频率Fvco = Fout * 3(因为输出有固定3分频)在PLL允许的VCO频率范围内。 - 配置BWADJ值:手册给出的公式是
BWADJ = ((PLLM + 1) >> 1) - 1,即(PLLM + 1) / 2再向下取整减1。例如,若PLLM = 15,则(15+1)/2=8,8-1=7。这个值用于优化PLL的环路带宽,使其与当前的M值匹配,从而获得最佳的抖动性能和锁定时间。务必正确设置,不恰当的BWADJ可能导致PLL锁定时间过长或输出时钟抖动超标。 - 等待至少5μs:这是PLL复位释放所需的最小时间,基于参考时钟周期。软件上通常用一个简单的延时循环来实现。
- 设置PLLSELECT=1:告诉时钟多路选择器,准备选择PLL的输出作为时钟源。注意,此时PLL还在复位状态,输出无效,但选择器可以先配置好。
- 设置PLLRST=0:释放PLL复位。PLL开始基于新配置的M、D值进行锁定。
- 等待PLL锁定时间:这是最关键也是最容易忽略的步骤。锁定时间至少需要
500 * REFCLK周期 * (PLLD + 1)。REFCLK周期就是输入时钟的周期。例如,如果输入时钟是100MHz(周期10ns),PLLD=1,那么最小锁定时间为500 * 10ns * 2 = 10μs。在实际编程中,强烈建议等待时间远大于这个最小值,比如等待100μs甚至1ms,并可以通过查询PLL状态寄存器(如果提供)来确认锁定,而不是单纯依赖延时。 - 设置BYPASS=0:切换到PLL模式。至此,PASS PLL开始输出稳定的、符合设定频率的时钟。
实操心得:在编写初始化代码时,一定要将上述步骤封装成一个函数,并且严格使用“读-修改-写”操作来访问PLL寄存器。手册中特别用“CAUTION”警告了这一点。因为这类控制寄存器中通常有很多保留位(Reserved),它们的值可能是敏感的,随意的写入操作可能改变它们,导致不可预知的行为。正确的做法是:先读取整个寄存器的值到一个临时变量,在临时变量上修改目标位域,然后再将临时变量的值写回寄存器。
2.3 时钟电气特性与PCB设计考量
手册的“PASS PLL Input Clock Electrical Data/Timing”部分给出了外部输入时钟PASSCLKP/N的电气要求。这通常是在硬件设计阶段,由硬件工程师关注的内容,但驱动/底层软件工程师也需要了解,以便在调试时判断是否是硬件问题。
- 周期与占空比:时钟周期(
tc)需要在3.2ns到6.4ns之间(对应频率约156.25MHz到312.5MHz)。高电平和低电平的脉冲宽度(tw)都需要占周期的45%到55%,即占空比要求接近50%。 - 上升/下降时间:信号在250mV电平变化范围内的转换时间(
tr,tf)需要在50ps到350ps之间。过慢的边沿可能导致时钟采样错误。 - 抖动:周期性抖动的峰峰值(
tj)不能超过100ps。过大的抖动会直接影响PLL的输出时钟质量,进而影响网络协处理器的时序裕量。
对于软件工程师而言,如果你的系统发现网络性能不稳定,在排查软件配置无误后,可以建议硬件同事用高速示波器测量一下PASSCLKP/N的波形,看看是否满足上述时序要求,特别是抖动指标。
3. EDMA3控制器:数据搬运的引擎
如果说CPU是系统的大脑,负责思考和决策,那么EDMA3就是不知疲倦的搬运工,负责把所有“原料”(数据)准时、准确地送到大脑面前,并把“产品”(处理结果)运送到指定位置。在C6670这种多核DSP中,高效利用EDMA3是提升整体性能的必由之路。
3.1 EDMA3架构与核心概念
C6670上有三个独立的EDMA3通道控制器(Channel Controller):EDMA3CC0, EDMA3CC1, EDMA3CC2。它们不是简单的复制,而是有明确分工:
- EDMA3CC0:专为MSMC(多核共享存储器)和DDR3子系统优化。它只有2个传输控制器(TC),但总线宽度为32字节,默认突发大小(DBS)为128字节,这表明它面向的是大块、高带宽的内存间数据传输。
- EDMA3CC1/CC2:用于其他外设和存储器的数据传输。它们各有4个TC,但总线宽度为16字节,DBS为64字节,更灵活,适合服务多种外设。
每个通道控制器都管理着一组DMA通道、QDMA通道和参数RAM(PaRAM)。理解这三者的关系是掌握EDMA3编程的关键:
- DMA通道:这是传统的、基于事件的传输通道。每个通道可以被一个特定的事件(如外设接收完成、定时器溢出)触发,也可以由软件手动触发。CC0有16个,CC1/CC2各有64个。
- QDMA通道:快速DMA通道。它没有独立的事件映射,触发方式更简单:软件直接向一个特定的PaRAM集写入数据即可触发传输。这种方式开销极小,非常适合软件发起的、零散的数据搬运。每个CC都有8个QDMA通道。
- PaRAM集:这是EDMA3的灵魂。每一次传输的所有信息(源地址、目的地址、传输维度、计数、索引、链接地址等)都存储在一个PaRAM集中。DMA通道或QDMA通道实际上只是PaRAM集的“触发器”和“执行器”。CC0有128个PaRAM集,CC1/CC2各有512个。
正交传输描述是EDMA3的一大特色。一次传输可以定义三个维度:
- 数组(Array):一组连续字节。由
ACNT定义字节数。 - 帧(Frame):多个数组。由
BCNT定义数组数量,SRCBIDX/DSTBIDX定义数组之间的地址偏移。 - 块(Block):多个帧。由
CCNT定义帧数量,SRCCIDX/DSTCIDX定义帧之间的地址偏移。 通过灵活设置这些参数和索引值,可以实现非常复杂的数据搬移模式,例如二维矩阵的转置、音频帧的重排等,而无需CPU干预。
3.2 通道控制器与传输控制器配置解析
手册中的表7-33和表7-34是硬件固定的配置,软件无法更改,但理解它们对于性能调优至关重要。
表7-33 EDMA3通道控制器配置
| 描述 | EDMA3 CC0 | EDMA3 CC1 | EDMA3 CC2 | 含义与影响 |
|---|---|---|---|---|
| DMA通道数 | 16 | 64 | 64 | CC0通道少,但专用于高带宽路径。CC1/CC2通道多,可连接更多外设。 |
| QDMA通道数 | 8 | 8 | 8 | 每个CC都有8个快速软件触发通道。 |
| 中断通道数 | 16 | 64 | 64 | 与DMA通道数对应,用于传输完成或错误中断。 |
| PaRAM集条目数 | 128 | 512 | 512 | PaRAM集是稀缺资源,复杂的传输链会消耗多个集,需要合理规划。 |
| 事件队列数 | 2 | 4 | 4 | 事件触发后进入队列排队。CC1/CC2队列更多,调度更灵活。 |
| 传输控制器数 | 2 | 4 | 4 | TC是实际执行读写操作的“工人”。CC1/CC2有更多“工人”,可并行处理更多传输请求。 |
| 内存保护区域数 | 8 | 8 | 8 | 用于设置不同主设备(Master)的访问权限,增强系统安全性。 |
表7-34 EDMA3传输控制器配置
| 参数 | EDMA3CC0 TC0/TC1 | EDMA3CC1 TC0/TC2 | EDMA3CC1 TC1/TC3 | EDMA3CC2 TC0/TC2 | EDMA3CC2 TC1/TC3 | 含义与影响 |
|---|---|---|---|---|---|---|
| FIFOSIZE | 1024字节 | 1024字节 | 512字节 | 1024字节 | 512字节 | 数据FIFO大小。TC从源端读数据先存入FIFO,再写入目的端。更大的FIFO可以更好地缓冲数据,应对总线延迟,提升长连续传输的效率。CC0的TC FIFO最大,与其高带宽角色匹配。 |
| BUSWIDTH | 32字节 | 16字节 | 16字节 | 16字节 | 16字节 | 读写数据总线宽度。决定了TC一次能搬运的数据量。CC0 TC的32字节宽度是其高带宽能力的硬件基础。 |
| DSTREGDEPTH | 4 | 4 | 4 | 4 | 4 | 目的FIFO寄存器组深度。决定了TC能同时处理多少个未完成的传输请求。深度为4意味着最多可排队4个传输。 |
| DBS | 128字节 | 64字节 | 64字节 | 64字节 | 64字节 | 默认突发大小。TC发起一次读或写命令所传输的最大字节数。应与总线位宽和系统支持的最大突发长度匹配。CC0的128字节与其32字节总线宽度(4次突发)相符。 |
性能调优提示:当你的应用需要极高的数据吞吐量(例如,从DDR3向MSMC搬运大型矩阵数据),应优先考虑使用EDMA3CC0及其TC。在配置PaRAM时,应尽量让每次传输的
ACNT(数组大小)是DBS的整数倍(对于CC0是128字节的倍数),这样可以最大化总线利用效率,减少零碎传输带来的开销。
3.3 寻址模式与事件映射
寻址模式:EDMA3支持常量和增量两种寻址模式。手册明确指出,在C6670上,常量寻址模式仅适用于VCP和TCP这两个译码协处理器。对于其他所有外设和内存(包括MSMC、DDR、其他外设),都必须使用增量寻址模式。这意味着,在配置PaRAM的SRC/DST地址时,对于绝大多数场景,你只需要关心起始地址,EDMA3会在每次传输后根据SRCBIDX/DSTBIDX等参数自动更新地址。除非你明确在为VCP/TCP配置DMA,否则可以忽略常量模式。
事件映射:这是连接外设与EDMA3通道的桥梁。手册中的表7-35、7-36、7-37详细列出了每个EDMA3CC的DMA通道与具体硬件事件的固定映射关系。例如,EDMA3CC1的通道0对应SPIINT0(SPI中断0),通道4对应I2CREVT(I2C接收事件)。这个映射是硬件固定的,不可编程更改。
这意味着,如果你想让EDMA3服务于SPI的接收数据搬运,你必须使用EDMA3CC1的通道0(或者也可能是通道1,取决于你用哪个SPI中断)。在软件初始化时,你需要:
- 找到对应外设事件映射的EDMA3CC和通道号。
- 为该通道分配一个PaRAM集,并配置好传输参数。
- 使能该通道的事件捕获。
- 使能该外设的事件产生。
当外设(如SPI)产生接收完成事件时,硬件会自动触发对应EDMA3通道的传输,完全无需CPU干预。
常见问题排查:“我的EDMA3配置好了,但就是不触发传输!” 这是最常遇到的问题之一。请按以下顺序排查:
- 事件映射核对:确认你使用的EDMA3通道号,是否与你想服务的外设事件在手册映射表中一致。这是最容易出错的一步。
- 外设事件使能:EDMA3通道使能了,但外设本身可能没有配置为产生DMA事件。例如,SPI需要配置相应寄存器来使能接收/发送DMA请求。
- PaRAM链接:如果是链式传输,检查链接到的下一个PaRAM集地址是否正确,以及该PaRAM集是否已正确配置。
- 中断与错误状态:查询EDMA3通道控制器的错误中断寄存器(
EDMACC_ERRINT)和事件丢失寄存器,看是否有错误发生或事件丢失。
3.4 中断与系统集成
EDMA3的传输完成或错误,可以通过中断通知CPU。每个EDMA3CC都有多个中断通道,可以映射到CPU的某个中断输入。更复杂的是,整个C6670的中断系统是一个多层网络,由芯片级中断控制器(CIC)进行路由。
手册图7-29和后续庞大的表格描述了系统事件如何通过CIC0/1/2,最终映射到各个C66x核心的12个可屏蔽中断(CPUINT4-15)或异常中断(EXCEP)。EDMA3的中断作为系统事件之一,也汇入这个网络。
对于软件工程师来说,要正确响应一个EDMA3传输完成中断,需要完成以下配置:
- EDMA3CC端:配置传输完成中断使能,并指定使用哪个中断号(例如
INT0)。 - CIC端:在对应的CIC模块中,将EDMA3产生的中断事件(如
EDMA3CC0_INT0)映射到CIC的某个输出事件。 - CorePac端:在CPU的Interrupt Controller中,将CIC输出的那个事件,映射到CPU的一个具体中断输入(如
CPUINT8),并设置好中断服务程序(ISR)的入口地址。
这个过程略显繁琐,但TI的芯片支持库(CSL)或实时操作系统(如SYS/BIOS)通常会提供封装好的API来简化配置。理解这个拓扑结构的意义在于,当你的中断不响应时,你知道该去检查哪一层的配置:是EDMA3没产生中断?是CIC没路由?还是CPU的中断控制器没使能?
4. 实战配置:从理论到代码
理解了原理,我们来看一个具体的配置例子:如何使用EDMA3CC1的通道0,响应SPI0的接收事件,将数据从SPI接收缓冲区搬移到MSMC内存中。
4.1 步骤分解与代码示例
假设我们使用TI的C66x CSL库进行开发。以下是一个简化的流程:
第一步:确定硬件资源根据手册表7-36,SPIINT0事件映射到EDMA3CC1的通道0。我们将使用这个通道。
第二步:配置PaRAM集我们需要找一个空闲的PaRAM集,比如paramSetId = 10。
#include <csl_edma3.h> #include <csl_edma3Aux.h> EDMA3_RM_Handle hEdmaRm; // 资源管理器句柄 EDMA3_DRV_Handle hEdmaDrv; // 驱动句柄 EDMA3_DRV_ChannelHandle hEdmaCh; // 通道句柄 EDMA3_DRV_PaRAMRegs paramSet; // PaRAM参数集 // 1. 初始化EDMA3驱动和资源管理器(略) // 2. 申请一个PaRAM集 CSL_Edma3ParamSetup myParamSetup = { .option = 0x00000000, // 具体选项,如传输完成中断使能等 .srcAddr = (uint32_t)SPI_RX_BUF_ADDR, // SPI接收缓冲区地址 .aCnt = 16, // 数组大小:每次SPI接收16字节(假设) .bCnt = 100, // 帧数:连续接收100个这样的数组 .cCnt = 1, // 块数:1块 .dstAddr = (uint32_t)MSMC_DST_ADDR, // MSMC中的目标地址 .srcBIdx = 16, // 源B索引:每个数组后,源地址增加16字节(连续) .dstBIdx = 16, // 目的B索引:每个数组后,目的地址增加16字节(连续) .srcCIdx = 0, // 块内不跳变 .dstCIdx = 0, .linkAddr = CSL_EDMA3_LINK_ADDR_NULL, // 传输完成后不链接到其他PaRAM .bCntReload = 0 }; // 使用CSL库函数填充paramSet结构 CSL_edma3SetPaRAM(hEdmaRm, paramSetId, &myParamSetup);第三步:配置并启用DMA通道
// 配置通道参数 EDMA3_DRV_ChannelConfig chConfig = { .paramId = paramSetId, // 关联的PaRAM集ID .eventQueueNo = 0, // 使用事件队列0 .chType = EDMA3_DRV_CHANNEL_TYPE_DMA, // DMA通道类型 .trigMode = EDMA3_DRV_TRIG_MODE_EVENT, // 事件触发模式 }; // 打开(申请)EDMA3CC1的通道0 hEdmaCh = EDMA3_DRV_requestChannel(hEdmaDrv, CSL_EDMA3_CC1, 0, &chConfig, NULL); // 使能该通道捕获事件(即允许SPI事件触发它) EDMA3_DRV_enableChannel(hEdmaDrv, hEdmaCh);第四步:配置SPI外设以产生DMA请求这需要配置SPI模块的相关寄存器,使其在接收FIFO达到一定阈值或接收完成时,产生一个DMA请求事件(对应SPIINT0)。具体寄存器配置取决于SPI的工作模式,此处略。
第五步:(可选)配置传输完成中断如果需要CPU在传输完成后被通知,则需在PaRAM的OPT字段中使能传输完成中断,并配置EDMA3CC1的中断映射以及CPU的中断控制器。
// 在myParamSetup.option中设置中断使能位 myParamSetup.option |= CSL_EDMA3_OPT_TCINTEN_MASK; // 配置EDMA3CC1,将通道0的传输完成映射到它的INT0输出 CSL_edma3HwChannelSetup(hEdmaRm, CSL_EDMA3_CC1, 0, ...); // 具体函数略 // 通过CIC和CPU中断控制器,将EDMA3CC1_INT0事件路由到CPU的某个中断线,并注册ISR4.2 高级技巧:使用链接(Linking)实现乒乓缓冲
EDMA3的强大之处在于链接机制。我们可以配置一个PaRAM集在传输完成后,自动加载(链接)另一个PaRAM集的配置,从而实现循环或乒乓操作,完全无需CPU干预。
场景:SPI持续接收数据,我们需要在缓冲区A和缓冲区B之间交替存储,避免数据覆盖。方案:
- 准备两个PaRAM集(Set1, Set2)。Set1的
dstAddr指向缓冲区A,linkAddr指向Set2的地址。Set2的dstAddr指向缓冲区B,linkAddr指回Set1的地址。 - 初始化通道使用Set1。
- 当SPI事件触发,EDMA3使用Set1的参数将数据搬到缓冲区A。传输完成后,硬件自动将Set2的参数加载到该通道的“影子PaRAM”中。
- 下一个SPI事件到来,EDMA3自动使用Set2的参数将数据搬到缓冲区B。传输完成后,又自动链接回Set1。 如此循环,实现了双缓冲乒乓操作,CPU只需在缓冲区满时处理数据即可。
// 伪代码示意 myParamSetupA.linkAddr = (uint32_t)CSL_edma3GetParamRamBase(hEdmaRm) + (paramSetId_B * PARAM_SET_SIZE); myParamSetupB.linkAddr = (uint32_t)CSL_edma3GetParamRamBase(hEdmaRm) + (paramSetId_A * PARAM_SET_SIZE); // 分别设置A和B的目的地址为BufA和BufB // 初始化通道时使用SetA通过这种方式,EDMA3就像一个拥有简单“脚本”能力的智能DMA,可以自主完成复杂的、周期性的数据传输任务。
5. 调试心得与避坑指南
在多年的C6670项目开发中,围绕PASS PLL和EDMA3的调试占据了大量时间。下面分享几个血泪教训:
关于PASS PLL:
- 锁定时间不足:这是最隐蔽的问题。手册给的是最小时间,在实际板卡上,由于电源噪声、PCB布局等因素,PLL可能需要更长时间才能稳定锁定。我的经验是,将锁定等待时间设置为计算值的10倍以上,或者直接等待1ms。更好的做法是,如果PLL有锁定状态位,一定要查询该位,而不仅仅是延时。
- 寄存器访问顺序:一定要严格遵守初始化序列。我曾试过先释放PLL复位再切换选择器(交换步骤7和8),结果导致系统在切换时钟源的瞬间出现毛刺,网络协处理器直接挂死。
- 电源与噪声:PLL对电源质量非常敏感。如果发现网络部分工作不稳定,时钟抖动大,除了检查配置,一定要测量PLL的模拟电源引脚(AVDD)是否干净。必要时增加滤波电容。
关于EDMA3:
- PaRAM集管理:PaRAM集是全局资源,容易被不同任务或不同核心的代码重复使用或修改。强烈建议在系统设计阶段就规划好PaRAM集的分配,例如,为每个核心或每个主要外设划分固定的PaRAM集范围,并通过软件锁或资源管理器进行分配,避免冲突。
- 事件丢失(Event Miss):如果外设产生事件的速度超过了EDMA3处理的速度(或者事件队列满),事件可能会丢失。EDMA3控制器有事件丢失检测寄存器。在调试时,如果发现数据不完整,可以检查这些寄存器。解决方法包括:优化传输参数减少单次处理时间、使用更高优先级的事件队列、或者让外设降低数据速率。
- 内存一致性:C66x核心有缓存(L1D, L2)。如果EDMA3搬运的目的地是CPU即将读取的内存,或者源地址是CPU刚写入的内存,必须手动维护缓存一致性。在DMA传输开始前,如果源数据可能在缓存中,需要将缓存写回(Writeback)到内存;在DMA传输完成后,如果目的数据将被CPU读取,需要将缓存中对应区域无效化(Invalidate)。忽略这一步会导致CPU读到旧数据(脏数据)或EDMA3读到旧数据。
- 性能瓶颈分析:当EDMA3性能达不到预期时,可以结合传输控制器的配置来分析。例如,如果频繁进行大量小数据块传输(
ACNT远小于DBS),总线利用率会很低。应尽可能将小传输合并成大的数组传输(增大ACNT),或者使用链接功能将多个小传输描述符链起来,让EDMA3一次性提交给TC,减少软件触发开销。
配置TMS320C6670的PASS PLL和EDMA3,就像在为一座高性能工厂铺设电力线路和自动化传送带。PLL的稳定是工厂运转的基础,而EDMA3配置的优劣则直接决定了原材料和成品流转的效率。希望这篇详细的解析能帮助你避开我当年踩过的那些坑,让这颗强大的多核DSP能在你的手中发挥出全部潜力。记住,底层配置无小事,每一行寄存器配置代码,都影响着系统最根本的稳定与性能。
