在工业控制领域,DSP(数字信号处理器)的固件升级一直是个重要课题。传统方式往往需要拆机连接JTAG接口,这在设备部署后变得极为不便。基于CAN总线的升级方案应运而生,它允许工程师通过现场总线网络直接对设备进行远程升级,大大提升了维护效率。
本方案基于TI的TMS320F28035 DSP芯片实现,主要特点包括:
本方案测试平台采用M新动力的DSP28035开发板,关键硬件配置如下:
| 硬件模块 | 型号/参数 | 备注 |
|---|---|---|
| DSP芯片 | TMS320F28035 | 主频60MHz,128KB Flash |
| CAN收发器 | SN65HVD230 | 支持最高1Mbps波特率 |
| 调试接口 | JTAG 14Pin | 用于初始BootLoader烧录 |
| 指示灯 | LED x3 | D400-D402用于状态指示 |
CAN接口硬件连接需要特别注意:
重要提示:CAN总线必须正确终端匹配,否则会导致通信不稳定。在总线两端各接一个120Ω电阻。
系统采用经典的BootLoader+APP双区设计:
code复制┌───────────────────────┐
│ BootLoader │
│ - CAN通信协议栈 │
│ - Flash编程算法 │
│ - 跳转控制逻辑 │
└───────────┬───────────┘
│
┌───────────▼───────────┐
│ APP区 │
│ - 用户应用程序 │
│ - 升级触发逻辑 │
└───────────────────────┘
F28035的128KB Flash空间划分如下:
| 地址范围 | 大小 | 用途 |
|---|---|---|
| 0x3F7000-0x3F7FFF | 4KB | BootLoader区 |
| 0x3F8000-0x3FEFFF | 28KB | APP区(用户程序) |
| 0x3FF000-0x3FFFFF | 4KB | 配置区(标志位等) |
BootLoader启动时执行以下关键初始化:
c复制void BootLoader_Init(void)
{
// 1. 关闭所有中断
DINT;
IER = 0x0000;
IFR = 0x0000;
// 2. 初始化系统时钟
InitSysCtrl();
// 3. 初始化CAN控制器
CAN_Init(500000); // 500Kbps波特率
// 4. 初始化GPIO
InitGpio();
// 5. 检查升级标志
CheckUpdateFlag();
}
CAN总线配置关键参数:
c复制void CAN_Init(uint32 baudRate)
{
// 1. 配置GPIO30/31为CAN功能
GpioCtrlRegs.GPBMUX2.bit.GPIO30 = 2; // CANRXA
GpioCtrlRegs.GPBMUX2.bit.GPIO31 = 2; // CANTXA
// 2. 初始化CAN控制器
ECanaRegs.CANMC.bit.CCR = 1; // 进入配置模式
while(ECanaRegs.CANES.bit.CCE != 1); // 等待配置模式
// 3. 设置波特率
uint16 brp = (LSPCLK_FREQ / (baudRate * 16)) - 1;
ECanaRegs.CANBTC.bit.BRP = brp;
ECanaRegs.CANBTC.bit.TSEG1 = 12;
ECanaRegs.CANBTC.bit.TSEG2 = 3;
ECanaRegs.CANBTC.bit.SJW = 3;
// 4. 退出配置模式
ECanaRegs.CANMC.bit.CCR = 0;
while(ECanaRegs.CANES.bit.CCE != 0); // 等待退出配置模式
}
Flash操作是BootLoader的核心功能,主要包括擦除和编程两个操作:
c复制// Flash扇区擦除
uint16 Flash_Erase(uint32 sectorAddr)
{
// 1. 解锁Flash
FlashRegs.FPWR.bit.PWR = 3;
FlashRegs.FBANKWAIT.bit.PAGEWAIT = 5;
FlashRegs.FBANKWAIT.bit.RANDWAIT = 5;
FlashRegs.FOTPWAIT.bit.OTPWAIT = 5;
// 2. 执行擦除
FlashRegs.FSM_WRITE_RECORD.bit.WRITE_RECORD = 0x55AA;
FlashRegs.FSM_WRITE_RECORD.bit.WRITE_RECORD = 0xAA55;
while(FlashRegs.FSM_WRITE_RECORD.bit.BUSY);
return SUCCESS;
}
// Flash数据编程
uint16 Flash_Program(uint32 dstAddr, uint16 *srcData, uint32 length)
{
// 1. 检查地址对齐
if(dstAddr & 0x1) return FAIL; // 必须16位对齐
// 2. 逐字编程
for(uint32 i=0; i<length; i+=2) {
*(uint16 *)(dstAddr + i) = srcData[i/2];
while(FlashRegs.FSM_WRITE_RECORD.bit.BUSY);
}
return SUCCESS;
}
C#上位机采用模块化设计:
code复制┌───────────────────────┐
│ 主控制界面 │
├───────────────────────┤
│ CAN通信模块 │
├───────────────────────┤
│ HEX文件解析模块 │
├───────────────────────┤
│ 升级协议处理模块 │
└───────────────────────┘
csharp复制public class CANComm
{
private ControlCAN.CAN_OBJ[] canObj = new ControlCAN.CAN_OBJ[1];
private uint deviceType = ControlCAN.VCI_USBCAN2;
private uint deviceInd = 0;
private uint canInd = 0;
public bool Init(uint baudRate)
{
ControlCAN.VCI_INIT_CONFIG initConfig = new ControlCAN.VCI_INIT_CONFIG();
initConfig.AccCode = 0x00000000;
initConfig.AccMask = 0xFFFFFFFF;
initConfig.Filter = 1;
initConfig.Mode = 0;
initConfig.Timing0 = 0x01; // 500Kbps
initConfig.Timing1 = 0x1C;
if(ControlCAN.VCI_OpenDevice(deviceType, deviceInd, 0) != 1)
return false;
return ControlCAN.VCI_InitCAN(deviceType, deviceInd, canInd, ref initConfig) == 1;
}
}
csharp复制public List<byte> ParseHexFile(string filePath)
{
List<byte> binData = new List<byte>();
string[] lines = File.ReadAllLines(filePath);
foreach(string line in lines)
{
if(!line.StartsWith(":")) continue;
int byteCount = Convert.ToInt32(line.Substring(1, 2), 16);
int address = Convert.ToInt32(line.Substring(3, 4), 16);
int recordType = Convert.ToInt32(line.Substring(7, 2), 16);
if(recordType == 0x00) // 数据记录
{
for(int i=0; i<byteCount; i++)
{
string byteStr = line.Substring(9+i*2, 2);
binData.Add(Convert.ToByte(byteStr, 16));
}
}
}
return binData;
}
本方案采用自定义CAN协议帧:
code复制┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
| 帧头 | 命令 | 序号 | 数据长度 | 数据... | 校验 |
└─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
各字段说明:
完整升级流程分为四个阶段:
现象:上位机无法与DSP建立通信
排查步骤:
现象:升级过程中通信中断
解决方案:
现象:写入后校验发现数据错误
解决方法:
在实际项目中,我们通过CAN总线成功实现了DSP28035的远程升级功能,平均升级时间约30秒(对于28KB的APP程序)。关键是要确保CAN总线的稳定性,建议在工业现场使用带屏蔽的双绞线,并做好接地处理。