星点匠心建站 星点匠心建站XD JIANXIN STUDIO
400-883-9527 免费定制方案
ARTICLE DETAIL

资讯详情

深耕新锐建站与运营推广的一线实战洞察。

TMS320F28P550调试踩坑实录:环境、烧写与外设全解析

TMS320F28P550调试踩坑实录:环境、烧写与外设全解析 1. 这块芯片到底什么来头为什么值得写一篇调试实录TMS320F28P550是TI C2000系列里比较新的一员主频做到150MHz带FPU、TMU、CLA专门为电机控制、数字电源、工业驱动这类实时控制场景设计的。和老的F2833x、F2806x相比它的外设资源更丰富尤其是内部集成了更多的PWM通道、ADC精度也提到了12位还有可配置逻辑块CLB这种灵活的外设做复杂控制算法的时候能省不少外部逻辑芯片。我拿到这块芯片做项目本来以为有以前F280049的经验打底上手会很快。结果真正开始调试才发现坑不在于芯片性能而在于开发环境、启动流程、外设初始化和一些小细节上。这篇文章把我实际踩过的、身边同事也踩过的调试问题整理出来不是官方手册的复读是真正在实验室里一个个现象、一个个排查堆出来的经验。写这篇文章适合谁看准备从老C2000平台迁到F28P55x的工程师、刚接触C2000但已经有一点嵌入式基础的人以及正在被CCS的诡异报错、串口乱码、PWM波形不对折磨的人。内容主要包括环境搭建、编译和Flash烧写、外设调试三个大方向最后补一份常见问题排查速查表方便你遇到问题的时候直接对照排查。2. 开发环境搭建踩过的坑CCS版本和仿真器的兼容性问题2.1 CCS版本选择不是越新越好而是要匹配芯片支持包我在项目初期用的是CCS 12.0创建工程的时候发现设备列表里根本没有TMS320F28P550这个型号。开始我还以为自己的CCS装坏了重装了一遍还是老样子查了TI官网才知道原因F28P55x是相对较新的芯片必须要用CCS 12.5及以上版本而且必须安装对应的C2000Ware版本单纯在里面找芯片型号是找不到的。我后来装的是CCS 12.8配合C2000Ware 5.02.00创建工程时就能正常识别F28P550了。这里有个很实用的建议C2000Ware下载完之后安装路径建议保持默认不要动。因为CCS的工程模板、链接命令文件CMD和启动代码都会通过环境变量去找C2000Ware的路径一旦路径变了工程编译的时候会报一堆“找不到文件”的错误排查起来非常痛苦。我在CCS安装上还建议你把编译器版本也看清楚。F28P55x要求TI编译器支持C2000指令集我用的是TI v22.6.1.LTS编译一切正常。如果你用的是GCC版本编译器部分外设库的宏定义会处理得不一样工程的兼容性会打折扣建议还是用TI官方编译器。2.2 仿真器连接失败不是板子坏了是供电和接地的问题仿真器我一开始用的XDS110连接F28P550的时候报错Error connecting to the target: (Error -2131 0x0) Unable to access device register。这个错误很典型第一反应是芯片锁死了但我检查了JTAG引脚接线没有问题后来用万用表一量发现核心板3.3V供电不稳只有2.9V左右。问题出在我用XDS110的5V输出给底板供电而底板上有几个芯片包括CAN收发器吃电流比较大XDS110的供电能力不够导致3.3V跌落。换成外部稳压电源给底板供电之后仿真器连接马上正常了。这个事给我一个教训调试F28P55x先确保目标板供电稳定不要偷懒用仿真器供电。另外JTAG线能短则短超过15cm就容易受干扰连接不稳定的时候先看这两点别急着怀疑芯片。2.3 CCS的在线调试界面频繁断连的另外一个原因连接问题和环境配置完毕之后接着碰到的就是CCS Debug模式下频繁掉线的问题。具体表现是在线仿真运行一两分钟CCS就弹出Lost connection to target。我一开始怀疑是仿真器固件问题更新了固件也没用。后来排查才发现是CCS里watch窗口刷新数据太多、太快把JTAG通讯带宽占满了。我在watch窗口加了数组变量一刷新就是几百个数据CCS默认刷新频率下每个周期都在疯狂读内存最终导致调试链路超时。解决办法有两个一是减少watch窗口的变量只关注核心状态量二是在Debug Configurations里面把Enable CIO和Enable silicon initialization选项关掉这两个会在每次连接时做一堆额外工作对实时性要求高的调试没必要开启。3. 编译和烧写阶段的问题CMD文件、Flash和RAM的分配逻辑3.1 编译报错之“内存溢出”明明RAM很大为什么还会溢出F28P550内部RAM挺大的但我在工程里加入控制算法和通信协议栈之后编译报了一个很头疼的错误error #10099: program will not fit into available memory关键是报错指向的是RAM段不是Flash。后来我打开工程的CMD文件一看就明白了。TI提供的默认CMD文件把.ebss、.sysmem、.stack等段都分配到了RAMLS0~RAMLS7而我把大量全局变量的初值都在启动时拷贝到了RAM显示缓冲区又占了一大块连续空间老兵新兵挤在一起RAM不够用了。我的处理思路是重新规划内存分配把.text代码段完全放在Flash里运行只在启动时把部分时间关键函数用#pragma RAM_FUNC挪到RAM执行。把大块的数据缓冲区单独放到RAMGS段和系统变量隔离开。扩大了stack段从默认的0x400扩到0x800因为控制算法里的中断嵌套比较深栈不够很容易PC跑飞。具体CMD修改我用了TI提供的F28P55x_Flash_lnk.cmd作为基础把RAMLS和RAMGS的分配重新划分保证每段的起始地址和长度合法同时没有物理地址重叠。3.2 Flash烧写的关键检查项供电、时钟、等待状态当程序编译通过烧录Flash的时候我也踩了一个典型的坑。用CCS的Flash Programmer烧写校验到50%左右报错Flash programming failed。一开始我以为是Flash芯片质量问题后来反复测试发现是Flash等待状态wait-state配置不对。F28P550在150MHz主频下跑Flash读取必须在初始化里把FlashWaitState配置成正确的值否则CPU访问Flash的速度跟不上程序烧进去启动就乱跑。我从工程模板的Device_init函数里找到了Flash_initModule这个函数把等待状态设成FLASHWAIT_5烧写之后再做回读校验问题就解决了。顺带说一个和烧写关系很大的细节烧Flash之前一定要确认芯片的boot模式引脚配置正确。F28P55x上电后会根据GPIO的状态决定从Flash启动还是从RAM启动、还是进入等待仿真器的模式类似串口下载模式。如果你GPIO配置不巧烧录的时候虽然能进调试模式但一旦复位就卡在bootloader里面不出来表现在现象就是程序完全没有运行。我后来用跳线帽把boot引脚固定到“Flash启动”模式复位之后程序就能正常跑起来了。3.3 Debug模式下正常、掉电重启就挂问题出在启动文件这是项目里最诡异的一个现象在CCS里F11单步、断点调试都正常数据都对但只要拔掉仿真器、重新上电程序就完全没反应。折腾了两天才找到原因。CCS的Debug模式在有仿真器连接时代码是从RAM启动或者由调试器直接加载到Flash然后从RAM运行_c_int00启动流程可以正常完成。但脱机复位后芯片要从Flash里重新搬运初始值这段代码在启动文件里如果某些段地址在CMD里定义不匹配程序就跳飞了。我的解决办法是在Device_init里面显式调用MemCfg_init和Flash_initModule确保在main函数真正开始之前Flash控制器的时钟、等待状态、内存配置都是正确的。另外还要检查boot时是否执行了EALLOW和EDIS配对某些寄存器在启动阶段不允许写入一旦非法访问就把程序锁死了。检查完这些后脱机重启就正常了。4. 外设调试实录串口、PWM、ADC和中断的控制权问题4.1 串口打印乱码不是波特率、不是电平是供电纹波用串口调试助手看数据发现输出全是乱码频率还不定。这类问题嵌入式工程师第一反应都是波特率对不对我量了串口引脚的波形波特率102400和配置一致帧格式也不对的话也说不过去。同事提醒我查一下电源纹波用示波器一量3.3V上面叠加了一个几百mV、频率大概100kHz的锯齿波串口逻辑电平在高电平附近抖动接收端采样错位自然就乱码了。根源是底板上一个DC-DC模块的补偿参数没调好纹波偏大。我换了一个低纹波的LDO给MCU单独供电之后串口输出稳定了。这块给两个建议串口调试时优先检查供电纹波其次再查波特率误差。某些USB转串口模块自身波特率误差就很大比如便宜的CH340在115200时误差超过2%C2000侧如果是内部时钟源精度也有限两边误差叠加起来很容易乱码。如果怀疑时钟精度最好用外部晶振。4.2 PWM波形不正常TBPRD和CMPA的数值范围被忽略了PWM模块调试时出现的问题不烧芯片但是行为很怪。我配置了ePWM4通道输出50kHz的PWM上下桥臂是互补带死区的用示波器一看频率确实是对的但占空比总是固定的怎么改CMPA都不变。检查驱动代码我发现一个隐蔽的错误F28P550的ePWM模块时基计数器TBPRD是16位的最大值65535我的PWM频率设定50kHz在150MHz的时钟下分频之后TBPRD刚好在1000多此时占空比改变几十上百是有效的但如果配置寄存器时没有注意到CMPA的实际装载值也是16位在写入时我用了带符号的int类型负值经过类型转换成无符号之后变成了很大的数PWM输出就变成极限占空比了。解决方式就是所有PWM相关的寄存器操作统一用uint16_t类型并且在写入CMPA之前做一个范围钳制saturation防止异常值灌进去。死区的设置也是一样很多老工程师喜欢把DBRED和DBFED设成一样的值但实际应用中开和关的死区时间往往需要不同设置。带感性负载的电机驱动关断死区要稍大一些否则容易桥臂直通但太大又会影响电流波形。这个要通过实际测试确定我的经验是先按开关频率的0.5%~1%起步然后用示波器看开关波形微调。4.3 ADC采到的数据跳变典型的多通道复用和采样窗口问题F28P550的ADC是12位的我在做三相电流采样时发现采集的数据有明显的周期性跳变尤其在电流过零点附近毛刺特别大。查了应用手册发现是多通道采样的采样保持时间不够。C2000的ADC虽然有多个SOCStart of Conversion通道但最终采样保持电路是复用的。如果触发源设置得太密前一个通道的采样保持还没有稳定下一个通道就开始转换了采样结果就会串扰。我调整了采样窗口把ACQPSAcquisition Prescale从默认值加大到足够长同时把SOC触发间隔拉开确保每个通道都有完整的采样保持时间再配合均值滤波数据就平滑了。另外一个隐藏问题ADC供电脚和参考电压。F28P550内部虽然有参考电压但引脚上必须接高质量的去耦电容。我调试时有一次把参考电压引脚的电容焊歪了导致ADC在一定的温度范围内读数出现了固定偏移这个在原理图设计阶段就要留意后期很难排查。参考电压建议用4.7uF和0.1uF电容并联尽量靠近引脚。4.4 中断不触发外设中断标志和PIE控制器的配合F28P550的中断系统沿用了C2000的PIE外设中断扩展架构我第一次配置ADC中断时中断服务函数怎么写都不触发后来查了例程发现漏了一步在PIE模块里要把对应Group的使能位打开同时在CPU层面也要使能对应的全局中断。这里有个顺序问题很关键必须先配置外设中断标志使能位再开PIE组使能最后开CPU全局中断EINT。如果顺序反了中断标志在外设里已经置位但PIE来不及响应这个标志可能就一直挂着等之后再开中断要么立刻误触发要么被后续的标志覆盖。排查中断问题时我推荐在ISR开头置一个GPIO翻转信号用示波器看这个引脚就能一秒判断中断到底有没有进来不用反复打断点看CCS窗口。这是嵌入式调试里很经典的一招很多老员工都在用。5. 电源、复位和时钟三大基础系统的排查实录5.1 上电复位异常复位引脚毛刺导致程序随机跑飞F28P550的复位引脚本身有内部上拉但外部干扰仍可能让它误触发。我在现场遇到过一台设备程序运行几分钟就死机看门狗也喂着复位电路也是常规的RC复位但示波器抓复位引脚发现每隔一会儿就有一个负脉冲幅度低于复位阈值芯片就复位了。这个负脉冲来源是旁边的接触器动作电磁干扰耦合进了复位电路。我把RC复位电路的电容从0.1uF加大到1uF并且加上一个TVS管在复位引脚上电快速瞬变脉冲群干扰测试就通过了。如果是频繁出现CRUB代码运行不稳定的情况记得先看复位引脚有没有毛刺别急着查软件逻辑。5.2 晶振不起振负载电容和反馈电阻的匹配问题F28P550使用外部晶振时不起振的概率也不小。我用的是24MHz无源晶振调试时晶振一直不起振检查了电源、引脚配置都正常。后来看了晶振厂家的推荐电路负载电容应该是18pF但我板子上用了两个9pF的等效负载电容约4.5pF匹配不对负性阻抗不足。更换两个18pF电容后晶振稳定起振主频也正常。这里有个计算公式外部两个负载电容的串联值再加上PCB寄生电容大约2~5pF就是晶振的实际负载电容。晶振参数要求的负载电容是18pF你外部就配两个33pF串联约16.5pF再加寄生电容就差不多了。另外要注意某些情况下晶振需要并联一个1MΩ左右的反馈电阻来保证起振。F28P550内部已经集成了反馈电阻但外部再放一个也不会有大影响主要是方便调试。5.3 内部振荡器漂移高速通信场景下容易暴露FF28P550内部有INTOSC1和INTOSC2两个内部振荡源精度在出厂时校准过常温下大概±1%到±2%。我在调CAN通信时发现两个板子之间CAN报文偶尔会出现错误帧用了外部晶振之后就再没出现过。这提醒我一个事如果项目里涉及高速串行通信比如CAN、SCI、SPI时钟源尽量用外部晶振内部振荡器做低速逻辑或者不需要严格时序的场合可以。在需要低功耗的场景下内部振荡器比较方便但精度要求高的时候宁可多花几毛钱加个晶振。当然有例外情况如果F28P550做的是纯模拟信号采样、不需要和外部设备同步用内部振荡器完全没问题。要结合项目实际场景权衡。6. 基于问题的工具提升从Keil习惯迁移到CCS环境的经验6.1 Keil和CCS调试逻辑的差异很多从STM32转过来的同事特别是熟悉Keil ST-Link这套流程的第一接触CCS会觉得很别扭。Keil里最常用的功能比如Watch窗口直接右键变量看数值、仿真时直接改外设寄存器在CCS里的操作路径完全不同。CCS里的快捷键默认是CtrlShiftD添加表达式到Expressions窗口看外设寄存器要到Registers窗口按外设分类展开。和Keil还有个很大区别CCS的Build和Debug是分开的工程配置你要切换Release优化和Debug带调试信息要进Project Properties里改不像Keil里点一下魔法棒就能切。6.2 GDB命令行调试在CCS中的等效用法如果你以前用过Linux下的GDB或者做过VSCode调试会觉得CCS某些地方不如GDB顺手。但CCS底层调试引擎也是类GDB的在Debug界面下方有一个Console标签可以输入类似mem、reg这样的命令。我调试F28P550时偶尔会用view memory来直接查看某段RAM地址的数据尤其是数组、结构体这类大块数据在变量窗口看不了全貌时直接在内存视图里跳转到对应地址看十六进制数据比一个个加变量方便得多。6.3 日志保存和离线分析别小看调试信息落盘F28P550跑控制算法的时候简单的串口打印也能做数据观测但毕竟是实时系统打印太频繁会影响执行效率而且数据也不连续。我在项目里用了一个很朴素的办法DMA把ADC采样值和控制量连续写入RAM里的环形缓冲区等缓冲区满了之后通过串口数据打包发给PC端工具再在PC端做波形分析。这个做法相当于把MCU当成了一个简易的数据记录仪。我用SSCOM或者XCOM这类串口调试助手就能收数据但数据量大的时候建议用支持协议解析的串口工具可以自定义帧格式把数据直接解析成曲线。个人体会是做嵌入式控制类项目单纯靠断点单步调试是走不远的尤其是带电机负载的情况下断点一停电气量就全部变化了你看到的现场已经不是现场了。不如把关键数据落盘实时性问题拿示波器看逻辑问题用日志和数据包分析这样调试效率反而高很多。7. F28P550使用经验总结与注意事项7.1 我调试F28P550时的几条硬性原则第一开发初期就确认好供电方案MCU电源和功率部分电源先分开用示波器量好纹波。电源问题会伪装成各种奇奇怪怪的现象串口乱码、复位跑飞、ADC跳变排查到后面往往都会汇聚到电源上。第二永远先认时钟。系统时钟起没起、配置在多少MHz、外设时钟有没有打开这个搞不清楚后面全是无头苍蝇。F28P550的时钟树比较复杂我建议画一个自己的时钟树表格标注每个外设的时钟源和分频系数随时对照。第三CMD文件和启动流程多看几遍。C2000和STM32最大的区别在于Flash运行方式代码段和数据段的存放位置直接影响系统稳定性。不要直接套用模板工程就完事了要把每个段的分布搞清楚尤其是增加大数组或者协议栈的时候。第四配置GPIO时先查该引脚有没有其他复用功能尤其是JTAG、ADC、PWM这些功能重叠的引脚。F28P550的GPIO复用非常灵活但也意味着容易配错。我调试时有一次把PWM输出配成了GPIO模式波形死活出不来其实就是PINMUX寄存器弄错了检查外设配置之前先检查引脚复用。7.2 实时性调试中的断点替代方案有电机或功率设备在跑的时候直接在CCS里打断点是很危险的行为不仅影响运行还可能导致控制时序崩溃甚至炸管子。我的做法是多用DMA搬运数据、用GPIO翻转测量时间戳、用串口或者CAN把数据发出来在PC端分析。用GPIO翻转加示波器测时间的方式比你在CCS里看cycle计数要直观得多。比如要测一个控制周期内各个任务分别耗了多少时间就在每个任务开始和结束翻转一个引脚几个任务用不同的引脚示波器上看高电平时长就能一目了然。7.3 固件升级和量产阶段的调试注意事项F28P550有一个比较方便的特性支持在线升级。量产时用CAN或者SCI做bootloader我项目里用的SCI方式通过串口接收固件数据写入Flash。这里最关键的是Flash分区bootloader区和应用区要严格隔离启动地址要对应正确还要设置App的有效标志位不然升级失败一次变砖就很麻烦。量产阶段调试用的串口打印不要全删掉可以保留一个调试等级的开关通过编译宏或者运行时参数控制。这样现场出了问题时不需要通过仿真器去读变量直接让现场人员用串口调试助手把日志发回来排查效率会高很多。这也是我多次出差处理现场问题后的体会。8. 常见问题速查表问题现象可能原因排查顺序仿真器连不上供电不稳、JTAG接线错误、芯片锁死1.量电压 2.检查接线 3.尝试unlock编译内存溢出CMD段分配不合理、全局变量过多1.分开RAM段 2.优化变量类型 3.检查栈空间Flash烧写失败等待状态配置错误、Flash保护位开启1.配置等待位 2.检查Flash配置 3.检查boot模式程序脱机不能跑CMD段和启动文件不匹配、boot引脚不对1.检查启动流程 2.检查boot引脚 3.检查Flash配置串口乱码供电纹波、波特率误差、接线问题1.量电源纹波 2.确认波特率 3.检查接线PWM占空比不变寄存器类型错误、CMPA范围溢出1.检查数据类型 2.加钳制 3.示波器看波形ADC跳变采样窗口短、参考电压不稳1.加大ACQPS 2.检查参考电压 3.均值滤波中断不触发PIE未使能、中断标志被吞1.配置PIE 2.开全局中断 3.检查ISR地址复位随机复位晶振起振慢、复位引脚干扰1.示波器抓复位脚 2.调整RC 3.加TVS程序跑飞栈溢出、看门狗没喂、数组越界1.检查栈 2.检查看门狗 3.检查数组边界8.1 一个容易被忽略的调试技巧用示波器看启动过程很多工程师调启动问题只会缠着CCS打断点但真正复位瞬间的逻辑在Debug下反而不容易复现。我调试F28P550上电不启动问题时会在main函数入口、外设初始化完成、主循环首行各翻转一个GPIO然后用示波器看这几个引脚的上电时序波形这样能够快速确认程序到底哪一步卡住了不需要仿真器介入。这个方法对于量产后的设备同样有效板子出问题后直接在现场用示波器测量这些测试点就能定位问题是在硬件上电、启动代码还是外设初始化阶段。测完再把测试点功能恢复成正常功能引脚就行不影响量产品。8.2 调试结束后的收尾清单每当我完成一个功能模块的调试都会做一个收尾检查把所有临时的测试代码、GPIO翻转、调试串口打印整理一遍去掉影响性能的保留有用的日志入口把寄存器配置量整理成文档把关键的波形截图存下来。这样等到下次复测或者改版的时候不需要重新摸索一遍。F28P550的调试过程其实不算难但坑是真的多。很多时候问题不在芯片本身而是我们习惯了某个平台的调试思路没及时切换过来。希望这份实录能帮你少走一点弯路。
返回列表