dsp28335的在线升级(IAP),can总线,锁了2个dsp芯片总算联调成功了。 总体包括两部分,基于ccs6.1.3的下位机工程;基于LabVIEW18.0的上位机工程;下位机的dsp上电由一次boot引导至flash,flash内根据cmd文件划分两个工程,分别二次引导程序(boot)和app程序;上位机解析hex文件,通过can通信完成在线升级操作。 上位机和下位机均带思路解析,附带本人调试过程的各种参考资料。
最近在搞DSP28335的远程升级方案,被CAN总线和双DSP联调折腾得够呛。原本以为移植个IAP功能就是改改跳转地址的事,结果发现从HEX文件解析到双机通信全是坑,实验室的示波器都快被我盯出火星子了...
下位机架构玩分家
DSP28335的Flash被我用cmd文件切成两个独立小区:0x3D000-0x3D7FF给二次引导程序(Boot2),0x3D800开始才是主程序(App)。关键在初始化时就得划清界限:
#pragma CODE_SECTION(InitFlash, "FLASHCODE") void InitFlash(void){ FlashRegs.FOPT.bit.ENPIPE = 1; //开流水线模式 FlashRegs.FBANKWAIT.bit.RANDWAIT = 5; //Flash等待周期 }这段代码必须放在FLASHCODE段执行,否则在操作Flash寄存器时直接死机。调试时用CCS的Memory Browser眼看着App区的代码被意外覆盖,最后发现是CMD文件中RAM到Flash的映射地址没做偏移补偿。
跳转黑魔法实践
从Boot2跳App的关键操作像个定时炸弹:
LB #0x3D800 ;绝对跳转到App入口 ESTOP0 ;手动断点保平安刚开始傻乎乎直接用C语言的函数指针跳转,结果发现编译器自动生成的LRET指令导致堆栈错乱。后来在跳转前手动关中断、清流水线才稳定:
__asm(" CLRC INTM"); //关总中断 __asm(" SPM 0"); //清流水线 __asm(" MOV AL, #0x3D800 >> 16"); __asm(" MOV AH, #0x3D800 & 0xFFFF"); __asm(" LCR ACC"); //长跳转LabVIEW上位机的骚操作
用LabVIEW解析Intel Hex文件时发现,标准VI库里的解析模块处理28335的16位地址会抽风。自己写了个分段解析器:
![LabVIEW数据流处理截图]
关键是把每行HEX记录的地址与全局偏移做累加,遇到04扩展地址记录就更新基地址。CAN发送时采用分帧策略,每包数据带CRC16和序列号,上位机这边用队列缓存避免数据堵塞。
双DSP的死亡缠绕
两个DSP芯片的CAN通信就像在跳探戈——一个乱步全盘皆输。调试时发现节点2总是收不到升级指令,用CAN分析仪抓包才发现波特率配置寄存器没同步:
CanaRegs.CANMC.bit.CCR = 1; //进入配置模式 CanaRegs.CANBTC.bit.BRP = 9; //250kbps时钟分频 CanaRegs.CANMC.bit.CCR = 0; //退出配置模式两个DSP的晶振误差导致实际波特率相差3%,后来改用自适应波特率检测才解决。最惊悚的是某次升级中途断电,Boot2区数据损坏,最后是通过GPIO强制进入紧急恢复模式才救活。
参考资料血泪史
- 《TMS320F2833x Boot ROM手册》第5章关于二次引导的坑点
- 某俄文论坛的CAN总线错误处理方案(谷歌翻译立功了)
- 自己写的HEX转BIN工具(带地址偏移补偿)
- 示波器测CANH/CANL波形时发现的振铃问题解决方案
现在看着两台DSP通过CAN总线秒级完成固件同步升级,感觉那些在实验室通宵改代码的日子突然就值了。下次谁敢说IAP简单,我反手就送他两个锁死的DSP开发板...