您的位置:首页 > 其它

基于CANoe的ECU Bootloader刷写软件

2016-02-23 14:24 881 查看
目标:

车辆ECU需要更新软件,通过OBD口实现,通过CAN总线实现,编程语言是CAPL。

刷写流程基于ISO15765-3;应用层基于UDS(ISO14229)诊断协议;TP层基于ISO15765-2;数据链路层和物理层基于ISO11898

实现:

1.图形用户界面使用CANoe自带的panel来实现,用户可以选取刷写文件,ECU的地址等信息,这些信息通过环境变量被程序访问,环境变量在CANDB++中编辑生成。



2.软件架构:

刷写工具解析s19 app,如果没有s19 app,那么可以使用HexView将HEX,BIN等app转成s19文件

依据ISO15765-3编写刷写流程代码,将app数据扔给应用层

应用层是基于UDS编写的,应用层在将数据扔给TP层

TP层将数据扔给数据链路层

数据链路层将数据扔给物理层,数据通过CAN总线被ECU接收



代码:

工作保密原因,只贴出UDS层的代码,秘钥也删了

includes{

}

variables{
char gECU[7]="Tester";

int     useExtendedId=0;                                      //use standard Id
long    useFC=1;                                             //use flow control
long    bs=8;                                                //block size of FC
long    stmin=20;                                            //set STmin to 10 ms

dword   tester_address=0x7c1;                               //tester address
dword   target_ecu_address=0x7c9;                           //BCM address
char    wait_rsp_text_event[18]="response received";        //used to wait for response

const int BUFFER_SIZE_2048=0x2048;
const int BUFFER_SIZE_1024=0x1024;
const int LENGTH_4=4;
byte      rxBuffer[BUFFER_SIZE_2048];                          //receive buffer
long      rxBufferLen=0;                                       //receive buffer length
dword     timeout=5000;
dword     min_request_distance=50;                            //minum distance between two request
dword     dist_request = 10;
char      gDebugBuffer[255];
}

/*
read fault memory
*/
int read_fault_memory(byte _sub_func,byte _status_mask){
byte request[3]={0x19,0x02,0x09};

rxBufferLen=0;
request[1]=_sub_func;request[2]=_status_mask;
OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

/*
sessionControl
*/
int session_control(byte _session_type){
byte request[2]={0x10,0x01};

request[1]=_session_type;
OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

/*
reset
*/
int reset(byte reset_type){
byte request[2]={0x11,0x01};

request[1]=reset_type;
OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

/*
securityAccess
*/
int security_access(byte security_level,byte seed_szie,char ecu_name[]){
//actual size of Seed & Key Arrays depends on ECU
byte      gSeedArray[2];
dword     gSeedArraySize   = 4;
char      gVariant[9]    = "Variant1";
char      gOption[7]     = "option";
dword     gMaxKeyArraySize = 4;
dword     gActualSize  = 0;

byte      request_seed[2]={0x27,0x01};
byte      send_key[6]={0x27,0x02,0xAA,0xAA,0xAA,0xAA};

byte      const_secu_flash[4]={};           //security const number for level flash for BCM
byte      const_secu_level1[4]={};          //security const number for level 1 for BCM
byte      const_secu_flash_rfcm[4]={};           //security const number for level flash for BCM

byte      seed[4]={0xAA,0xAA,0xAA,0xAA};                       //store the seed received from server
byte      _key[4]={0xAA,0xAA,0xAA,0xAA};                       //store the key generated by tester
int       i=0;

request_seed[ 1 ] = security_level;send_key[ 1 ] = security_level + 0x01;
OSEKTL_DataReq(request_seed,elcount(request_seed));
if(wait_server_response(request_seed,timeout)!=0){
write("fail to retrive seed while unlocking ECU");
return -1;
}

for(i=0;i<seed_szie;++i){
seed[i]=rxBuffer[i+2];
}

gSeedArraySize = seed_szie;gMaxKeyArraySize = seed_szie;
//generate_key(const_secu_flash_rfcm,seed,_key);
diagSetTarget(ecu_name);
DiagGenerateKeyFromSeed(seed, gSeedArraySize, security_level, gVariant, gOption, _key, gMaxKeyArraySize, gActualSize);

for(i=0;i<gActualSize;++i){
send_key[i+2]=_key[i];
}

OSEKTL_DataReq(send_key,2+gActualSize);
return wait_server_response(send_key,timeout);
}

_Diag_GetError (char buffer[])
{
//called if error in DiagGenerateKeyFromSeed occurs
snprintf(gDebugBuffer,elcount(gDebugBuffer),"%s", buffer);
write("CALLBACK %s", gDebugBuffer);
}

/*
routineControl
*/
int routine_control(byte _routine_control_type,byte _routine_id[],byte data_record[],int data_record_length){
byte request[BUFFER_SIZE_1024];
int index=0;

request[0]=0x31;
request[1]=_routine_control_type;
request[2]=_routine_id[0];
request[3]=_routine_id[1];

for(index=0;index<data_record_length;++index){
request[index+4]=data_record[index];
}

OSEKTL_DataReq(request,data_record_length+4);

return wait_server_response(request,timeout);
}

/*
generate key according to the received seed
*/
void generate_key(byte const_secu[],byte seed_secu_flash[],byte securityKey[]){
byte key1_secu_flash[4]={0x00,0x00,0x00,0x00};
byte key2_secu_flash[4]={0x00,0x00,0x00,0x00};
int i=0;
byte tmp=0x00;

for(i=0;i<4;++i){
key1_secu_flash[i]=seed_secu_flash[i]^const_secu[i];
}

for(i=0;i<2;++i){
tmp=seed_secu_flash[i];
seed_secu_flash[i]=seed_secu_flash[3-i];
seed_secu_flash[3-i]=tmp;
}

for(i=0;i<4;++i){
key2_secu_flash[i]=seed_secu_flash[i]^const_secu[i];
}

for(i=0;i<4;++i){
securityKey[i]=key1_secu_flash[i]+key2_secu_flash[i];
}
}

/*
communicationControl
*/
int communication_control(byte _control_type,byte _communication_type){
byte request[3]={0x28,0x00,0x00};

request[1]=_control_type;request[2]=_communication_type;

OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

/*
controlDTCSetting
*/
int control_dtc_setting(byte _DTC_setting_type){
byte request[2]={0x85,0x00};

request[1]=_DTC_setting_type;

OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

/*
tester Present
*/
int tester_present(byte sub_function){
byte request[2]={0x3e,0x00};

request[1]=sub_function;

OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

/*
writeDataByID
*/
int write_data_by_id(byte did[],byte _data_record[],int _data_record_length){
byte request[256];
int i=0,_did_length=2;

request[0]=0x2E;

for(i=0;i<_did_length;++i){
request[1+i]=did[i];
}

for(i=0;i<_data_record_length;++i){
request[1+_did_length+i]=_data_record[i];
}

OSEKTL_DataReq(request,1+_did_length+_data_record_length);
return wait_server_response(request,timeout);
}

/*
requestDownload
*/
int request_download(byte _memory_address[],int _memory_address_length,byte _memory_size[],int __memory_size_length){
byte request[256];
int i=0;

request[0]=0x34;request[1]=0x00;request[2]=0x44;

for(i=0;i<_memory_address_length;++i){
request[3+i]=_memory_address[i];
}

for(i=0;i<__memory_size_length;++i){
request[3+_memory_address_length+i]=_memory_size[i];
}

OSEKTL_DataReq(request,3+_memory_address_length+__memory_size_length);
return wait_server_response(request,timeout);
}

/*
tansferData
*/
int transfer_data(byte _block_sequence,byte _upload_data[],int _upload_data_length){
byte request[BUFFER_SIZE_2048];
int i=0 , status = 0;

request[0]=0x36;request[1]=_block_sequence;

for(i=0;i<_upload_data_length;++i){
request[2+i]=_upload_data[i];
}

OSEKTL_DataReq(request,_upload_data_length+2);
status = wait_server_response(request,timeout);

return status;
}

/*
requstTransferExit
*/
int request_transfer_exit(){
byte request[1]={0x37};

OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

int read_data_by_id(byte did[]){
byte request[3]={0x22,0x00,0x00};

request[1]=did[0];
request[2]=did[1];

OSEKTL_DataReq(request,elcount(request));
return wait_server_response(request,timeout);
}

OSEKTL_FirstFrameIndication( long sourceadr, long destadr, long rxCount )
{
/* Print message to write window */
//write("CAPL: %s: FF indication called, SA= 0x%02lx, TA= 0x%02lx, RxCount = %ld (AE=%d)", gECU, sourceadr, destadr, rxCount, OSEKTL_GetRecentAE());
}

//error handle
OSEKTL_ErrorInd(int error)
{
switch (error)
{
case 1:     write("----CAPL: Error (%d): Timeout while waiting for CF", error);     break;
case 2:     write("----CAPL: Error (%d): Timeout while waiting for FC", error);     break;
case 3:     write("----CAPL: Error (%d): Wrong Sequence Number", error);            break;
case 4:     write("----CAPL: Error (%d): TP_DLL busy", error);                      break;
case 5:     write("----CAPL: Error (%d): Unexpected PDU", error);stop();                   break;
case 6:     write("----CAPL: Error (%d): Timeout while waiting for Tx-Ack", error); break;
case 7:     write("----CAPL: Error (%d): WFT Overrun", error);                      break;
case 8:     write("----CAPL: Error (%d): Buffer overflow", error);                  break;
case 9:     write("----CAPL: Error (%d): Wrong parameter", error);                      break;
default:    write("----CAPL: Error (%d): unknown error", error);                    break;
}
}

//request confirm
OSEKTL_DataCon(long status)
{
if (status != 0)
{
//write("CAPL: %s: data sent using normal addressing", gECU);
}
else
{
write("----CAPL: %s: tx error, status is %d", gECU, status);
}
}

OSEKTL_DataInd( long rxCount )
{
dword glhandle=0;

/* Get received data */
OSEKTL_GetRxData( rxBuffer, 4095 );
rxBufferLen=rxCount;

//signal response received
TestSupplyTextEvent(wait_rsp_text_event);
}

//process will suspend for tTime ms to wait for response
int wait_server_response(byte request[],dword _tTime){
long status=0;
int result=0;
long flag=5;

flag=2;result=0;status=0;

//loop while response pending
while(flag>=0)
{
status=testWaitForTextEvent(wait_rsp_text_event,_tTime);
if(status<0){
write("service %x:fail to wait server response",request[0]);
return -1;
}else if(status==0){
write("service %x:timeout while waiting for server\'s response",request[0]);
return -1;
}

result=checkResponse(request);

if(result==-3){
write("response pending");
flag=5;
}

if(result==-2){
write("Warning:unexpected positive response");
flag--;
}

if(result==-1){
write("service %x:negative response received",request[0]);
break;
}

if(result==0){
//write("positive response received\n");
break;
}
}

if(result<0){
msgBeep(5);
return -1;
}

return 0;
}

/*
check response
return 0 if positive response received
otherwise return -1,-2,-3,0
*/
int checkResponse(byte request[]){
if(rxBufferLen<=0){
write("Error:empty response reveived\n");
return -1;
}
else{
if(rxBuffer[0]==request[0]+0x40){
//write("positive response received\n");
return 0;
}else if(rxBuffer[0]!=0x7F&&rxBuffer[0]!=(rxBuffer[0]+0x40)){
//unexpected positive response
return -2;
}
else if(rxBuffer[0]==0x7F&&rxBuffer[1]==request[0]){
if(rxBuffer[2]!=0x78)
{
//write("Error:negative response received\n");
return -1;
}else{
//response pending
return -3;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: