目标:
车辆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;
- }