尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

TMS32F28P550调试踩坑实录:XDS110连接失败到PIE中断排查全记录

TMS32F28P550调试踩坑实录:XDS110连接失败到PIE中断排查全记录 上周拿到一块用TMS32F28P550做的控制板我连上XDS110打开CCS满怀信心地点下Debug按钮结果弹出来的不是熟悉的下载进度条而是一串报错。接下来两天我几乎把能踩的坑都踩了一遍连接失败、烧进去不跑、串口没输出、中断不触发。这篇实录就是那两天排查过程的完整记录适合正在调C2000系列、尤其是F28P55x这颗芯片的工程师参考也适合那些习惯了STM32调试流程、刚切到TI C2000平台的朋友提前避雷。先说清楚我这次的环境芯片是TMS32F28P550下面简称F28P550调试器是XDS110IDE是CCS 12.x另外备了一台示波器、一个USB转串口模块PC端串口调试助手用的是SSCOM。整个调试链路就是CCS通过XDS110连接芯片的JTAG口程序里再用SCI外设把状态打印到串口。C2000系列的调试逻辑和主流ARM MCU差别不算大但细节上的坑比预想中多得多。1. 换了新芯片却沿用老套路F28P550调试前的环境梳理这颗F28P550属于TI C2000实时MCU家族和常见的F28004x、F2837x是同一个生态外设命名、寄存器风格、启动流程都一脉相承。我原本以为项目从F280049C迁移过来会很顺结果第一轮就栽了。事后复盘问题出在我对“新芯片”的定义太乐观型号变了引脚分配变了电源时序要求变了调试探针的接法细节也不完全一样。1.1 调试工具链不是只有CCS很多人一提到“调试”就只想到IDE里的Debug按钮实际上C2000的调试链路里至少有三个角色各管一摊CCS负责编译、下载、断点、单步、寄存器查看是主界面XDS110是JTAG/cJTAG调试探针负责把CCS的调试指令翻译成芯片能懂的JTAG时序UniFlash是独立烧录工具有些连接问题在CCS里表现得很模糊但在UniFlash里能得到更直接的反馈比如“连接成功但Flash校验失败”。串口调试助手在这里扮演的角色是“第三只眼”。芯片连不上调试器时如果芯片里已经有一段能跑的引导程序通过串口输出状态信息是一条非常重要的排查通道。所以我建议任何C2000调试环境都至少要准备两条链路JTAG调试链路和SCI串口打印链路两条腿走路。1.2 拿到新板子先量电源再开IDE这块板子第一天上电时XDS110能识别到目标电压但CCS一连接就报错。我量了一下3.3V供电轨纹波到了200mV以上而且上电瞬间的爬升速度非常慢接近10ms才从0拉到3.3V。XDS110在探测目标板时会先读取目标电压如果电压不稳或者纹波过大探针和芯片之间的逻辑电平判断就会乱套。后来我用线性稳压器单独给数字电源轨供电纹波压到50mV以内CCS连接就正常了。这个坑和芯片本身关系不大纯粹是电源设计问题但它在调试流程里最容易跳出来干扰判断。2. XDS110连接失败一条从“换探针”到“查线序”的完整排查链路CCS里点Debug后第一次报错信息是Error connecting to the target: (Error -2131 0x0) Unable to access device register.看到-2131这种错误码大部分人的第一反应是探针坏了或者芯片锁死了。我当时也这么想差点下单买新XDS110。后来冷静下来把排查过程拆成了四步每步都排掉一个怀疑项。2.1 先查物理层JTAG线序和接插件这块板的JTAG座子是10Pin的引脚定义和TI官方标准一致。我拿着万用表逐个量探针和芯片引脚之间的连通性发现TMS和TCK两根线在转接板上焊反了。也就是说调试器发出的时钟线和数据线完全错位XDS110自然读不到芯片寄存器。JTAG线序错误是非常隐蔽的坑尤其当你用的是“看起来兼容”的转接板时。很多第三方转接板把GND、TMS、TCK、TDO、TDI的顺序做得和TI原厂不一致你照着原厂原理图排针插一样能插进去但就是连不上。我的建议是拿到新板子第一步不急着插调试器先拿万用表测TMS对地、TCK对地的阻值确认引脚顺序和调试器定义一致。2.2 确认目标电压和复位引脚状态线序修好后CCS报错变成了“Unable to set target voltage”。XDS110的VCC引脚需要检测目标板的逻辑电平如果这个引脚悬空或者板子没上电探针根本不知道以什么电平标准去驱动JTAG信号。我检查了板子的供电电路发现模拟电源轨和数字电源轨是分开的而JTAG接口的VCC参考来自数字轨。接线没问题但数字轨的LDO输出电容虚焊导致XDS110检测到的电压偏低。补焊电容之后电压检测正常。这个环节的经验是XDS110上的Target Voltage显示一定要在CCS的Target Configuration里看如果显示0V或者明显低于预期先不要怀疑探针回去查板子电源。2.3 降低JTAG时钟频率能解决一大批“玄学”问题还有一次连接失败是在线有点长的情况下出现的排线拉到了20cm以上CCS默认的JTAG时钟频率下信号完整性就不够了。这种问题报错码千奇百怪什么-1135、-151都可能出现。在CCS的Target Configuration里找到XDS110的属性把JTAG TCLK从默认的5MHz降到1MHz甚至500kHz问题就消失了。低速JTAG对长线、飞线、杜邦线都更友好而且对普通调试场景来说下载速度慢那么一点完全无感。我后来养成的习惯是所有手工焊接的板子一律先降到1MHz再调试。2.4 用UniFlash做连接性验证区分硬件问题和软件问题CCS连接失败的报错信息有时候会让人很迷惑因为它会夹杂一些工程配置的干扰项。我一般会单独打开UniFlash选择对应的芯片型号只做一次连接测试。UniFlash的连接测试比CCS更底层它不关心你的工程配置、linker命令文件、编译选项只验证JTAG链路是否通、芯片ID是否能读出来。如果UniFlash能读出芯片ID说明物理链路没问题CCS报错大概率出在工程配置或者目标配置上如果UniFlash也连不上那就是硬件链路的问题继续查线序、电源、复位。3. 程序烧进去了一复位就“失忆”Boot模式与FLASH入口问题连接问题解决后程序能烧进去了在Debug会话里单步运行、观察变量都正常。但一退出Debug模式断开调试器重新上电芯片完全没有反应LED不闪串口也不打印。这种“仿真时活蹦乱跳脱机就死给你看”的现象在C2000平台上有三个高发原因启动模式引脚配置不对、代码链接到了RAM而不是FLASH、FLASH等待状态没配好。我挨个说。3.1 Boot引脚电平决定了复位后跑哪份代码C2000芯片内部有一段固化在ROM里的Boot ROM上电复位后CPU先执行Boot ROM里的引导程序通过采样一组GPIO引脚的电平决定下一步启动到哪种模式从FLASH启动、从SCI启动、从SPI启动、还是进等待模式。这块板的原理图上Boot引脚的默认状态是靠电阻上下拉决定的。我拿万用表量下来复位瞬间这几个引脚的组合落到了“SCI Boot”模式也就是说芯片一直在等待串口引导命令自然不跑FLASH里的程序。这个问题的隐蔽性在于你在CCS里下载程序后调试器接管了CPU并直接把PC指到了FLASH入口看起来一切正常但一旦复位Boot ROM按引脚电平来根本不认识你的FLASH程序。排查方法也很简单复位后看这组GPIO引脚的电平组合对照数据手册里的Boot模式表确认是不是落到了FLASH启动。3.2 检查链接脚本你的代码真的在FLASH吗Boot引脚改对后C2000版本的工程里还有另一个坑工程里如果用的是RAM版本的linker cmd文件编译出来的代码段只放在RAM里烧录时虽然能写进FLASH但复位后FLASH入口处根本没有有效的启动代码。我这次确认了一下CCS工程里默认生成的cmd文件有两个版本一个把代码放到FLASH、运行时可拷贝到RAM执行另一个只放在RAM。Debug模式下用前者完全没问题但脱机跑必须用带FLASH段的cmd文件并且在程序里把.text、.cinit这些段放到FLASH地址范围。检查方法是编译后看map文件入口地址_c_int00应该在FLASH范围而不是RAM范围。3.3 FLASH等待状态主频高却不给FLASH调整时间最后还有一个C2000特有的问题从FLASH取指执行时FLASH本身有访问等待周期。如果CPU主频跑得很高而FLASH等待状态寄存器没有设置足够的等待周期芯片会随机跑飞、复位或者压根不执行。这个问题在Debug模式下不明显因为调试器接管后可能把代码拷贝到了RAM执行绕过了FLASH的慢速取指。后来我在程序初始化里加了一段代码根据系统时钟频率动态配置FLASH等待状态脱机运行才稳定下来。等状态的配置值得看具体型号的数据手册F28P55x的FLASH模块和寄存器和老款C2000略有差异不能想当然地照搬老工程。4. 串口调试助手一直空白或乱码时钟配置引发的一连串怪象程序跑起来之后我想靠串口打印确认运行位置。结果SSCOM串口调试助手要么一片空白要么收到一堆乱码。这类问题在串口调试里太常见了但常见不代表好排它的根因层次非常多。我把自己的排查链路完整列一遍。4.1 第一步永远是确认有没有信号发出来先把示波器探头接到SCI TX引脚按一下板子上的复位键观察有没有脉冲。如果示波器上干干净净说明芯片根本没发出数据如果有脉冲但PC端收不到才需要考虑电平转换和接线。我这块板的SCI TX接到USB转串口模块之前中间过了一级电平转换芯片。示波器上看到TX引脚有3.3V的脉冲但USB转串口模块收到的却是0V问题就出在方向控制脚上。这种电平转换芯片的DIR引脚如果没接对单向数据还好双向数据就会两边抢。4.2 检查GPIO复用和外设时钟别让配置“静默失效”确认有信号之后接下来看SCI外设本身有没有正确初始化。F28P550的引脚默认是GPIO功能要开启SCI功能必须设置对应的GPIO复用寄存器。这步漏了引脚上当然不会有外设信号。另外C2000的SCI外设挂在低速外设时钟LSPCLK上如果LSPCLK分频配置错误波特率也会跟着错。我这次的表象是串口助手偶尔能收到一个字符但内容完全对不上而且每次收到的内容还不一样。4.3 波特率误差计算公式在这里起作用C2000 SCI波特率寄存器的设置公式是BRR LSPCLK / (波特率 × 8) - 1举个例子假设外部晶振配置后LSPCLK是25MHz目标波特率9600BRR 25000000 / (9600 × 8) - 1 324.52取整到324实际波特率实际波特率 25000000 / (8 × 325) ≈ 9615.4误差约0.16%在UART可接受范围内。问题是当时我把PLL配置错了系统时钟从预期的100MHz跑成了80MHzLSPCLK跟着变成20MHz波特率误差一下到了20%以上串口自然完全读不懂。这种时钟导致的串口“乱码”最迷惑人的地方在于它看起来像电平问题或接线问题。我那次排查到最后是老老实实把PLL配置、LSPCLK分频、SCI波特率寄存器这三层拉通算了一遍才算清楚误差从哪来的。嵌入式调试里数据手册里的公式不是摆设关键时刻能救命。4.4 别忘了共地USB转串口和板子必须同一个参考地还有一种“串口时好时坏”的情况追根溯源是USB转串口模块和板子没有共地。USB转串口模块由电脑USB口供电板子由自己的电源供电两者如果之间没有一根GND线连接UART电平的参考地就不一致表现为偶尔能收到几个字符、大部分时间乱码。这个问题在台式机后置USB口和板子电源插在不同的排插上时特别容易出现。解决办法很简单串口模块的GND和板子GND之间一定接一根线不要嫌麻烦。5. 中断函数一次都不进PIE跳转表和PIEACK的隐藏细节串口通了之后我接着调试一个外设中断现象是主循环里轮询外设标志位时发现事件确实发生了但中断服务函数一次都没进。这种情况比进了中断但逻辑不对更让人头大因为你要先搞清楚中断请求到底在哪一层被“扣住”了。5.1 C2000的中断机制不是简单的NVIC用惯了ARM的工程师拿到C2000最容易在中断上栽跟头。ARM MCU的中断控制器统一管理所有外设中断配置相对线性C2000则是先经过外设自身的中断标志再到PIE模块打包最后才到CPU的IER和INTM开关。C2000的PIE模块把外设中断分成12个组每组最多8个中断源CPU只有一个总中断入口PIE负责根据向量表把CPU跳转到对应的ISR。这个设计意味着你的ISR名字就算写对了如果PIE向量表没填、PIE使能位没开、IER对应位没置1中断一样不会触发。5.2 PIEACK寄存器同组中断被“按住”的经典原因那次排查过程中我第一次用断点停在主循环里手动查看IER和IFR发现外设中断标志IFR已经置位了IER也开着但CPU就是没有跳转到ISR。继续往下查是PIEACK寄存器。PIEACK的作用像一个闸门某个PIE组的中断申请送到CPU后PIEACK对应位会被置1阻止同组后续中断继续申请。CPU响应完中断向量后ISR里必须向PIEACK写1清零闸门才会重新打开。我当时的问题就是ISR里只清了外设中断标志忘了清PIEACK。于是第一次中断触发了ISR也执行了但执行完出来之后这个PIE组的闸门一直是关着的之后同组的中断请求全被按住CPU永远看不到。这个坑排查起来很恶心因为单次触发是正常的一进ISR打断点看寄存器也看不出问题必须连续触发两次以上才能复现。5.3 标志位的volatile声明和编译器优化另一类“中断不进”其实是进了但表现不明显和中断本身没关系。主循环里判断事件标志的代码如果变量没有加volatile修饰编译器在-O2以上优化级别可能把这个变量优化成寄存器缓存值导致循环永远看不到中断里更新的内容。我在F28P550上调试时遇到过类似情况中断里确实把标志置1了但主循环一直没反应。加volatile、或者把优化级别改成-O0问题消失。嵌入式开发里共享变量不加volatile属于原则性错误但在一个新平台的第一次调试里它出现的频率远比你想象的高。6. 多块板子连测时怎么把“经验”变成可复用的排查步骤当一块板子调通之后后面还有好几块同样型号的板子等着调试。如果每块板子都从头开始摸效率太低。我这次在调试后期把踩过的坑整理成了一套固定的联调流程效果很好这里分享出来。6.1 做一个板卡自检固件把关键状态主动吐出来我专门写了一个“自检版”固件烧进板子的FLASH里。上电之后这个固件依次完成以下动作检查系统时钟把PLL配置后的SYSCLK、LSPCLK通过串口打印出来轮询并打印关键GPIO的电平状态确认复位后的Boot引脚电平组合触发一次外设中断确认PIE链路通不通打印中断是否触发成功打印FLASH启动后的版本号和CRC校验值确认代码确实跑在FLASH里。这个自检固件配合SSCOM串口调试助手的日志保存功能可以做到上电后3秒内判断一块板子的大致健康状况。SSCOM的日志保存带时间戳多块板子连续测试时日志文件能留下完整对比线索。6.2 批量板子出现同一问题的共因分析方法第二块板子烧录后不跑我还以为是老问题结果发现Boot引脚电平完全正常。后来对比发现这批板子的FLASH供电电容有一路虚焊导致FLASH写入后校验失败程序看似烧进去了实际上校验不过就被丢弃了。多块板子一起测的时候如果同一个环节反复出问题先别急着逐块修停下来想想它们之间的共同点是不是同一批物料、同一道焊接工序、同一台贴片机贴的同一类电容。把多个板子的问题合并看往往比单独修一块更快定位到产线上的系统问题。6.3 用调试命令脚本快速抓取异常现场CCS的调试界面支持通过脚本或命令行方式与目标板交互底层调试协议和GDB的调试思路很像连接目标、读取寄存器、读取内存、修改内存。遇到偶发性问题手动在界面里点点点往往来不及抓现场我习惯提前准备一个脚本批量读取关心的几个寄存器和全局变量输出到文本文件。这种自动化抓取方式在排查“跑飞”“随机复位”这类问题时特别有用程序跑飞后怎么停下来的不重要重要的是跑飞瞬间PC跑到哪了、关键的几个寄存器是什么值。脚本化抓取快、可重复、不会漏信息比人肉眼盯着调试界面靠谱得多。我自己用下来的体会是调试经验的价值不在于记住了多少个错误码而在于遇到没见过的现象时能不能系统地沿着“硬件链路→时钟链路→外设配置→中断链路”一层层拆。这次在F28P550上踩的每一个坑最后都能归类到这四条链路之一把链条拉通问题基本就浮出水面了。也希望这篇实录能帮你少走几个弯路。
返回列表