最近在学习UDS,目的是编写一个上位机,用来刷软件和部分诊断功能的实现。网上找了很多资料,大部分还收费,还好通过努力找到了一篇文章,虽然它的代码不能直接用,但通过尝试修改和增加部分内容,勉强可以实现刷写功能,现在就以该脚本为基础,写一个简单的BootLoader刷写工程。以下是这边文章的连接:

https://blog.csdn.net/qq_34309267/article/details/104887793icon-default.png?t=O83Ahttps://blog.csdn.net/qq_34309267/article/details/104887793

在此首先感谢这篇文章的作者,让大部分刚入门的同学能够初步实现刷写的功能,有成果就有继续学习的动力,再次对作者表示感谢!

下面先展示一下我在原代码基础上,编写的工程界面和刷写过程中的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)。

转载请注明出处!

Logo

获取更多汽车电子技术干货

更多推荐