概述
一套完整的基于TI28x系列的can BootLoader系统,包括上位机和BootLoader。上位机的IDE为vs2022,编言为c#,can驱动基于周立功can盒。硬件为TI TMSF280049C开发板。将过程记录。
基于can总线的dsp280049c升级方案
bootloader源码,上位机源码,使用说明。
已经通过项目验证。
上位机
项目整体界面设计长下面这个样子,分了菜单栏、设备选型连接、文件选择、刷写控制、刷写信息显示、几个部分,界面简洁清新。
文件选择部分包括应用文件和驱动文件,应用文件时必须的,驱动文件是可选的,文件类型是hex。
刷写控制主要是启动ECU刷写流程,刷写采用多线程设计,提高刷写的整体效率,同时增加刷写进度条,可以及时了解刷写进度。
刷写信息显示主要是对刷写过程中的阶段进行显示,帮助用户知晓当前刷写的具体进程以及帮助出现问题时的故障排查。
开发过程
项目采用最新的VS2022进行开发,采用面向对象的方式进行模块化设计,减少模块间的耦合,方便以后增加新的功能模块;另外,采用多线程的方式,将报文接收、界面响应、刷写流程等部分分为线程,异步接收和发送,最大程度的避免由于软件处理不及时导致的丢帧问题,这点在实车测试时显得很重要,也是为什么很多上位机在实验室可以刷写,但在实车环境成功率就非常低。
刷写流程代码:
public process()
{
HexAPP1BlockList = new List<DataBlock>();
HexDriBlockList = new List<DataBlock>();
}
#endregion
#region 开始线程
public void setBTStart(bool start)
{
if (start)
{
BTThread = new Thread(BTprocess);
BTThread.IsBackground = true;
BTThread.Start();
}
else
{
if (BTThread != null)
{
BTThread.Join(); //等待线程结束
BTThread = null;
}
}
}
#endregion
#region 扩展会话-读取DID
private uint kuozhan()
{
changeToExtendedMode(); //进入扩展会话
session.dataToSend.waitEvent.WaitOne(INTERVAL);
result = CheckReceivedData(1, 0x50, 2, 0x03, "进入扩展会话 成功!", "进入扩展会话 失败!");
/* ----------------------------------------------------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
Check_compilation_condition();//检查编译条件
session.dataToSend.waitEvent.WaitOne(INTERVAL);
result = CheckReceivedData(1, 0x71, 2, 0x01, "检查编译条件 成功!", "检查编译条件 失败!");
}
/* ----------------------------------------------------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
stopDTC();//停止记录故障码
session.dataToSend.waitEvent.WaitOne(INTERVAL);
result = CheckReceivedData(1, 0xC5, 2, 0x02, "停止记录故障码 成功!", "停止记录故障码 失败!");
OBC.instance.progressBar_boot.Value = 5;
OBC.progressBar_boot_ValueChanged(OBC.instance.progressBar_boot.Value);
}
/* ----------------------------------------------------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
result = terminateCommunication(); //通信控制
Thread.Sleep(INTERVAL);
OBC.instance.boot_listBox.Items.Add("停止通信 成功!");
OBC.instance.boot_listBox.SelectedIndex = OBC.instance.boot_listBox.Items.Count - 1;
/* result = CheckReceivedData(1, 0x68, 2, 0x03, "通信控制 成功!", "通信控制 失败!");
*/
}
/* ----------------------------------------------------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
readDID_86(); //读取DID_86
session.dataToSend.waitEvent.WaitOne(INTERVAL);
result = CheckReceivedData(1, 0x62, 3, 0x86, "读取DID_86 成功!", "读取DID_86 失败!");
}
/* ----------------------------------------------------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
readDID_59(); //读取DID_59
session.dataToSend.waitEvent.WaitOne(INTERVAL);
result = CheckReceivedData(1, 0x62, 3, 0x59, "读取DID_59 成功!", "读取DID_59 失败!");
OBC.instance.progressBar_boot.Value = 8;
OBC.progressBar_boot_ValueChanged(OBC.instance.progressBar_boot.Value);
}
return result;
}
#endregion
#region 流程(编程会话--复位)
public void BTprocess()
{
//*******************************预编程阶段************************************************************************
if (!OBC.flag_18f0e5f4)
{
result = kuozhan();
if (result == ERROR)
{
return;
}
}
//***********************************主编程阶段***************************************************
Programming_session(); //编程会话
session.dataToSend.waitEvent.WaitOne(INTERVAL);
result = CheckReceivedData(1, 0x50, 2, 0x02, "进入编程会话 成功!", "进入编程会话 失败!");
OBC.instance.progressBar_boot.Value = 9;
OBC.progressBar_boot_ValueChanged(OBC.instance.progressBar_boot.Value);
/* -------------------------------------------------------------------------------------------------------------*/
byte[] seed = new byte[4];
if (result != TXandRX.ERROR)
{
result = 0;
Secure_access(); //27 安全访问
session.dataToSend.waitEvent.WaitOne(TimeOut);
OBC.instance.boot_listBox.Items.Add("请求种子 成功!");
result = TXandRX.OK;
break;
}
}
if (result == 0)
{
OBC.instance.boot_listBox.Items.Add("请求种子 失败!");
return;
}
uds_receive.receive_id_A4orAB.Clear();
}
/* ----------------------------------------------------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
sendkey(seed); //计算秘钥
session.dataToSend.waitEvent.WaitOne(TimeOut);
result = CheckReceivedData(1, 0x67, 2, 0x0A, "安全访问 成功!", "安全访问 失败!");
}
/* ----------------------------------------------下载dirver---------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
result = 0;
TXandRX.crc = 0xFFFFFFFF;//CRC初始值
OBC.instance.boot_listBox.Items.Add("开始下载Flash驱动!");
result = Download.writeBlockData(OBC.process.HexDriBlockList, 0);
if (result != TXandRX.OK)
{
OBC.instance.boot_listBox.Items.Add("Flash驱动下载失败!");
return;
}
OBC.instance.boot_listBox.Items.Add("Flash驱动下载成功!");
}
/* ------------------------------------------------写入指纹----------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
writefingerprint(); //写入指纹
Thread.Sleep(long_INTERVAL);
result = CheckReceivedData(1, 0x6E, 2, 0xF1, "写入指纹 成功!", "写入指纹 失败!");
}
/* ----------------------------------------------下载app---------------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
OBC.instance.boot_listBox.Items.Add("开始下载APP应用程序...");
result = Download.writeBlockData(OBC.process.HexAPP1BlockList, 1);
if (result != TXandRX.OK)
{
OBC.instance.boot_listBox.Items.Add("APP应用程序下载失败!");
return;
}
OBC.instance.boot_listBox.Items.Add("APP应用程序下载成功!");
}
/* ------------------------------------------------检查依赖性----------------------------------------------------------*/
if (result != TXandRX.ERROR)
{
Check_compilation_3101FF0100(); // 检查依赖性
Thread.Sleep(INTERVAL);
result = CheckReceivedData(1, 0x71, 2, 0x01, 3, 0xFF, "检查编译依赖性 成功!", "检查编译依赖性 失败!");
}
/* ------------------------------------------------复位----------------------------------------------------------*/
if (result != ERROR)
{
RESET();
Thread.Sleep(INTERVAL);
result = CheckReceivedData(1, 0x51, 2, 0x01, "复位 成功!", "复位 失败!");
OBC.instance.progressBar_boot.Value = 100;
OBC.progressBar_boot_ValueChanged(OBC.instance.progressBar_boot.Value);
}
整个刷写速度的话,200K的hex文件大概20S刷写完毕。
界面的设计比较简洁,干技术的审美也只能这样,大家不要吐槽,整体效果比较花(笑哭),各个部分进行分割,然后就成了现在这个样子。
下位机bootoader
有需求或者问题的小伙伴请与作者联系 2446764657(q)
希望对有相似需求的有帮助。
版权声明:本文为CSDN博主「明稚君」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。