基于UDS的CANoe BootLoader刷写上位机
基于UDS 的BootLoader刷写工具,利用CAPL语言编写上位机脚本,这里仅实现bin文件的刷写过程!
最近在学习UDS,目的是编写一个上位机,用来刷软件和部分诊断功能的实现。网上找了很多资料,大部分还收费,还好通过努力找到了一篇文章,虽然它的代码不能直接用,但通过尝试修改和增加部分内容,勉强可以实现刷写功能,现在就以该脚本为基础,写一个简单的BootLoader刷写工程。以下是这边文章的连接:
在此首先感谢这篇文章的作者,让大部分刚入门的同学能够初步实现刷写的功能,有成果就有继续学习的动力,再次对作者表示感谢!
下面先展示一下我在原代码基础上,编写的工程界面和刷写过程中的trace报文,先上图:
首先说一下它这个工程哈,没用任何.dll文件,纯CAPL代码硬写的,所以读起来对于刚入门同学有点费劲,然后呢,因为它里面有报文和环境变量,所以要建一个.dbc工程。
整体的刷写流程如下:
当然,这里还要仿真一个ECU,用来回复通讯。逻辑很简单,单帧报文就回复积极响应,多帧报文,就回复流控帧就好了,代码如下:
/*@!Encoding:936*/
includes
{
}
variables
{
message 0x0 temp_msg ={dlc=8};
message 0x0 resp_msg ={dlc=8};
message 0x0 FC_msg ={dlc=8};
long Cont=0;
}
on start
{
FC_msg.byte(0)=0x30;
}
on message *
{
if(this.id==0x7C8)
{
FC_msg.id=0x7C0;
//FC_msg.id=0x20;
if(this.byte(0)<0x0a)
{
if(this.byte(1)==0x10)
{
resp_msg.byte(0)=0x04;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=0x00;
resp_msg.byte(4)=0x32;
resp_msg.byte(5)=0x01;
resp_msg.byte(6)=0xf4;
output(resp_msg);
}
if(this.byte(1)==0x28)
{
resp_msg.byte(0)=0x04;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=0x00;
resp_msg.byte(4)=0x32;
resp_msg.byte(5)=0x01;
resp_msg.byte(6)=0xf4;
output(resp_msg);
}
if(this.byte(1)==0x27)
{
if(this.byte(2)==0x01)resp_msg.byte(0)=6;
else resp_msg.byte(0)=2;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=0x00;
resp_msg.byte(4)=0x32;
resp_msg.byte(5)=0x01;
resp_msg.byte(6)=0xf4;
output(resp_msg);
}
if(this.byte(1)==0x31)
{
resp_msg.byte(0)=5;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=0x03;
resp_msg.byte(3)=0xFF;
resp_msg.byte(4)=0xFF;
resp_msg.byte(5)=0x01;
resp_msg.byte(6)=0x00;
output(resp_msg);
}
if(this.byte(1)==0x11)
{
resp_msg.byte(0)=2;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=this.byte(3);
resp_msg.byte(4)=this.byte(4);
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(resp_msg);
}
if(this.byte(1)==0x37)
{
resp_msg.byte(0)=1;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=this.byte(3);
resp_msg.byte(4)=this.byte(4);
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(resp_msg);
}
if(this.byte(1)==0x22)
{
resp_msg.byte(0)=7;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=this.byte(3);
resp_msg.byte(4)=this.byte(4);
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(resp_msg);
}
if(this.byte(1)==0x2E)
{
resp_msg.id=0x7C0;
resp_msg.byte(0)=this.byte(0);
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=this.byte(3);
resp_msg.byte(4)=this.byte(4);
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(resp_msg);
}
if(this.byte(1)==0x85)
{
resp_msg.id=0x7C0;
resp_msg.byte(0)=this.byte(0);
resp_msg.byte(1)=this.byte(1)+0x40;
resp_msg.byte(2)=this.byte(2);
resp_msg.byte(3)=this.byte(3);
resp_msg.byte(4)=this.byte(4);
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(resp_msg);
}
//if(this.byte(1)!=0x3E) output(resp_msg);
}
if(this.byte(0)>0x0a)
{
if(this.byte(0)>>4==1)
{
Cont=((this.byte(0)&0xf)*0x100+this.byte(1))/7;
if(this.byte(2)==0x34)
{
resp_msg.byte(0)=3;
resp_msg.id=resp_msg.id=0x7C0;;
resp_msg.byte(1)=this.byte(2)+0x40;
resp_msg.byte(2)=0x20;
resp_msg.byte(3)=0xFF;
resp_msg.byte(4)=0x00;
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(FC_msg);
}
if(this.byte(2)==0x36)
{
resp_msg.byte(0)=3;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(2)+0x40;
resp_msg.byte(2)=this.byte(3);
resp_msg.byte(3)=0x00;
resp_msg.byte(4)=0x00;
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(FC_msg);
}
if(this.byte(2)==0x31)
{
resp_msg.byte(0)=5;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(2)+0x40;
resp_msg.byte(2)=0x03;
resp_msg.byte(3)=0xFF;
resp_msg.byte(4)=0xFF;
resp_msg.byte(5)=0x01;
resp_msg.byte(6)=0x00;
output(FC_msg);
}
if(this.byte(2)==0x2E)
{
resp_msg.byte(0)=3;
resp_msg.id=0x7C0;
resp_msg.byte(1)=this.byte(2)+0x40;
resp_msg.byte(2)=this.byte(3);
resp_msg.byte(3)=this.byte(4);
resp_msg.byte(4)=this.byte(5);
resp_msg.byte(5)=0x00;
resp_msg.byte(6)=0x00;
output(FC_msg);
}
}
if(Cont==0) output(resp_msg);
Cont--;
}
}
}
说一下Tester节点代码吧!大概两千行,写的挺冗余的,有些函数基本用不到,比方说关于S19文件的处理,因为本身从内容上看,不是刷.s19文件的,而是刷写bin文件的,所以,关于S19文件解析的部分就省略掉了,我大概省略了这几个函数,全部deactive掉了。
然后,timdowload函数内容也进行了省略,原来的有些冗余,基本就是让其从$10 03服务开始执行。
然后,再on message PEPS_Diag_Tx函数中,我也省略首帧和多帧这种情况,在刷写过程中,ECU一般只发单帧或流控帧,很少会发首帧FF和连续帧CF这种情况。
这里面有几个问题,就是27服务,只是简单的对seed进行移位操作,没有进行算法处理,各位感兴趣的读者,可以按照自己的算法添加进去,同时,在仿真ECU里面加入这种操作,相信会很有意思,另外,CRC校验这一块我还没仔细弄,就是按照原来的代码搞上去了,反正是调通了,这里需注意以下一点,在$31的正响应中应注意一点,如下图:
基本上满足以上要求,随便找一个Bin文件,只要其地址能够覆盖要求的刷写地址,基本都能按照基本逻辑进行数据刷写操作。这里面的$28服务应该是功能寻址,后面我要改一下!
时间有限,需要源代码的,请点赞+留言+关注,达到一定量后我会分享给大家(for free)。
转载请注明出处!
更多推荐
所有评论(0)