终于有时间整理下基于CANoe的UDS Bootloader,网上也看到了有其他网友分享的例子,基于OSEK_TP,在新版本的CANoe里面,已经被新的接口取代了。
本刷新软件是基于CANoe 8.5, 编程语言是CAPL,刷写流程基于ISO15765-3,支持读S19文件。
基于diagSendRequest 和on diagResponse。
主界面如下:
刷写Trace 如下:
代码如下:
关于密钥部分,只是做了 简单的字节顺序调整,可以根据自己项目要求调整密钥算法。
variables
{
long dwFile;
char s19Filename[500];
byte dataBuffer[0x0FFFFF];
long data_len = 0;
long transferData_idx=0;
int iRespTimeout=500;
enum{Extended_Session=0,TesterPresent,Disable_DTC,Disable_Communication,Programming_Session,Pending_Programming,Security_Access_Seed,Security_Access_Key,Erase_Flash,Request_Download,Transfer_Data,Transfer_Exit,Reset,Stop}prog_step=Extended_Session;
enum {PROG_NOT_STARTED,PROG_INPROGRESS,PROG_STOPED}prog_status=PROG_NOT_STARTED;
enum {Pre_programming,Programming,Post_Programming}programming_state;
const int gSeedArraySize= 4;
const int gKeyArraySize= 4;
byte gSeedArray[gSeedArraySize];
byte gKeyArray[gKeyArraySize];
long MEM_START_ADDR = 0x001000;
long MEM_END_ADDR = 0x001FFF;
long MEM_SIZE = 0;
byte sequence_num=1;
msTimer delayTimer;
}
on envVar Env_Start
{
if(@Env_Start ==1)
{
if(dwFile!=0) /*S19 File*/
{
programming_state = Pre_programming;
prog_status = PROG_INPROGRESS;
prog_step=Extended_Session;
@Env_Progress =0;
display_status("Preprogramming.......",'T');
Preprogramming_seq();
}
else
{
display_status("ERROR - Load S19 File",'F');
}
}
}
on envVar Env_Stop
{
if(@Env_Stop ==1)
{
if(prog_status==PROG_INPROGRESS)
{
prog_status = PROG_STOPED;
prog_step = Stop;
programming_state=Pre_programming;
@Env_Progress =100;
display_status("Flasing Interrupted",'F');
}
}
}
on envVar Env_FilePath
{
dwFile= getvalue(Env_FilePath,s19Filename);
}
void Preprogramming_seq()
{
if(prog_status == PROG_INPROGRESS)
{
switch(prog_step)
{
case Extended_Session:
diagSendRequest(dr_ExtendSession);
display_status("1.1 Extended Session",'T');
prog_step = TesterPresent;
break;
case TesterPresent:
diagSendRequest(dr_3E_00);
display_status("1.2 TesterPresent",'T');
prog_step = Disable_DTC;
break;
case Disable_DTC:
diagSendRequest(dr_85_DisDTC);
display_status("1.3 Control DTC",'T');
prog_step = Disable_Communication;
break;
case Disable_Communication:
diagSendRequest(dr_28_DisAll);
display_status("1.4 Communication Control",'T');
prog_step = Security_Access_Seed;
break;
case Security_Access_Seed:
diagSendRequest(dr_27_SeedReq);
display_status("1.5 Request Seed",'T');
prog_step = Security_Access_Key;
break;
case Security_Access_Key:
Seed2Key();
diagSetParameterRaw(dr_27_KeyReq, "securityKey", gKeyArray, gKeyArraySize);
diagSendRequest(dr_27_KeyReq);
display_status("1.6 Send Key",'T');
prog_step = Programming_Session;
break;
case Programming_Session:
diagSendRequest(dr_ProgSession);
display_status("1.6 Programming Session",'T');
programming_state=Programming;
prog_step = Erase_Flash;
break;
default:
break;
}
}
}
void Programming_seq()
{
byte memAddr[4];
byte memSize[4];
byte buff[512];
int i;
if(prog_status == PROG_INPROGRESS)
{
switch(prog_step)
{
case Erase_Flash:
memAddr[0] = (byte)(MEM_START_ADDR>>24);
memAddr[1] = (byte)(MEM_START_ADDR>>16);
memAddr[2] = (byte)(MEM_START_ADDR>>8);
memAddr[3] = (byte)(MEM_START_ADDR);
memSize[0] = (byte)(MEM_SIZE>>24);
memSize[1] = (byte)(MEM_SIZE>>16);
memSize[2] = (byte)(MEM_SIZE>>8);
memSize[3] = (byte)(MEM_SIZE);
diagSetParameterRaw(dr_31_EraseFlash, "memory_addr", memAddr, 4);
diagSetParameterRaw(dr_31_EraseFlash, "memory_size", memSize, 4);
diagSendRequest(dr_31_EraseFlash);
display_status("2.1 Erase Flash",'T');
prog_step = Request_Download;
break;
case Request_Download:
memAddr[0] = (byte)(MEM_START_ADDR>>24);
memAddr[1] = (byte)(MEM_START_ADDR>>16);
memAddr[2] = (byte)(MEM_START_ADDR>>8);
memAddr[3] = (byte)(MEM_START_ADDR);
memSize[0] = (byte)(MEM_SIZE>>24);
memSize[1] = (byte)(MEM_SIZE>>16);
memSize[2] = (byte)(MEM_SIZE>>8);
memSize[3] = (byte)(MEM_SIZE);
diagSetParameterRaw(dr_34_ReqDownload, "memory_addr", memAddr, 4);
diagSetParameterRaw(dr_34_ReqDownload, "memory_size", memSize, 4);
diagSendRequest(dr_34_ReqDownload);
display_status("2.2 Request_Download",'T');
prog_step = Transfer_Data;
Read_s19File(s19Filename);
break;
case Transfer_Data:
for(i=0;i<512;i++)
{
buff[i]=dataBuffer[transferData_idx++];
}
diagSetParameter(dr_36_TransferData, "blockSequenceCounter", sequence_num);
diagSetParameterRaw(dr_36_TransferData, "transferData", buff,512);
diagSendRequest(dr_36_TransferData);
if(sequence_num==0xFF)
{
sequence_num =0;
}
else
{
sequence_num ++;
}
@Env_Progress = transferData_idx*100/data_len;
if(transferData_idx>=data_len)
{
prog_step = Transfer_Exit;
sequence_num =1;
transferData_idx=0;
@Env_Progress = 100;
}
break;
case Transfer_Exit:
diagSendRequest(dr_37_ReqTransferExit);
display_status("2.4 Request TransferExit",'T');
programming_state=Post_Programming;
prog_step = Reset;
break;
default:
break;
}
}
}
void Post_programming_seq()
{
if(prog_status == PROG_INPROGRESS)
{
switch(prog_step)
{
case Reset:
diagSendRequest(dr_EcuReset_01);
display_status("3.1 Ecu Reset",'T');
prog_status = PROG_STOPED;
prog_step = Stop;
programming_state=Pre_programming;
break;
default:
break;
}
}
}
on diagResponse *
{
byte data[4096];
long size;
diagResponse * resp; // declare response with no concrete interpretation
size=this.GetPrimitiveSize(); // get length of response
this.GetPrimitiveData(data, elcount(data)); // copy actual response from "on diagResponse *" into data array
switch(data[0])
{
case 0x67: // UDS: SecurityAccess_Process positive Response
if(data[1]==0x01)
{
gSeedArray[0]=data[2];
gSeedArray[1]=data[3];
gSeedArray[2]=data[4];
gSeedArray[3]=data[5];
}
case 0x50:// UDS: DiagnosticSessionControl_Process positive Response
case 0x51: // UDS: EcuReset_Process positive Response
case 0x7E: // UDS: TestPresent positive Response
case 0x71: // UDS: Routine Control positive Response
case 0x68: // UDS: CommunicationControl positive Response
case 0x74: // UDS: RequestDownload positive Response
case 0x76: // UDS: TransferData positive Response
case 0x77: // UDS: RequestTransferExit positive Response
case 0xC5: // UDS: ControlDTCSetting positive Response
setTimer(delayTimer,10);
break;
case 0x7F:// UDS: Negative Response
break;
default:
break;
}
}
on timer delayTimer
{
if(programming_state==Pre_programming)
{
Preprogramming_seq();
}
else if(programming_state==Programming)
{
Programming_seq();
}
else
{
Post_programming_seq();
}
}
void Seed2Key(void)
{
gKeyArray[0]=gSeedArray[3];
gKeyArray[1]=gSeedArray[2];
gKeyArray[2]=gSeedArray[1];
gKeyArray[3]=gSeedArray[0];
}