基于CANoe的ECU Bootloader刷写软件

目标:

        车辆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层的代码,秘钥也删了

[cpp]  view plain  copy
  1. includes{  
  2.     
  3. }  
  4.   
  5. variables{  
  6.   char gECU[7]="Tester";  
  7.   
  8.   int     useExtendedId=0;                                      //use standard Id  
  9.   long    useFC=1;                                             //use flow control  
  10.   long    bs=8;                                                //block size of FC  
  11.   long    stmin=20;                                            //set STmin to 10 ms  
  12.   
  13.   dword   tester_address=0x7c1;                               //tester address  
  14.   dword   target_ecu_address=0x7c9;                           //BCM address  
  15.   char    wait_rsp_text_event[18]="response received";        //used to wait for response  
  16.   
  17.   const int BUFFER_SIZE_2048=0x2048;  
  18.   const int BUFFER_SIZE_1024=0x1024;  
  19.   const int LENGTH_4=4;  
  20.   byte      rxBuffer[BUFFER_SIZE_2048];                          //receive buffer  
  21.   long      rxBufferLen=0;                                       //receive buffer length  
  22.   dword     timeout=5000;  
  23.   dword     min_request_distance=50;                            //minum distance between two request  
  24.   dword     dist_request = 10;  
  25.   char      gDebugBuffer[255];  
  26. }  
  27.   
  28. /* 
  29.   read fault memory 
  30. */  
  31. int read_fault_memory(byte _sub_func,byte _status_mask){  
  32.   byte request[3]={0x19,0x02,0x09};  
  33.     
  34.   rxBufferLen=0;  
  35.   request[1]=_sub_func;request[2]=_status_mask;  
  36.   OSEKTL_DataReq(request,elcount(request));  
  37.   return wait_server_response(request,timeout);  
  38. }  
  39.   
  40. /* 
  41.   sessionControl 
  42. */  
  43. int session_control(byte _session_type){  
  44.   byte request[2]={0x10,0x01};  
  45.     
  46.   request[1]=_session_type;  
  47.   OSEKTL_DataReq(request,elcount(request));  
  48.   return wait_server_response(request,timeout);  
  49. }  
  50.   
  51. /* 
  52.   reset 
  53. */  
  54. int reset(byte reset_type){  
  55.   byte request[2]={0x11,0x01};  
  56.     
  57.   request[1]=reset_type;  
  58.   OSEKTL_DataReq(request,elcount(request));  
  59.   return wait_server_response(request,timeout);  
  60. }  
  61.   
  62. /* 
  63.   securityAccess  
  64. */  
  65. int security_access(byte security_level,byte seed_szie,char ecu_name[]){  
  66.   //actual size of Seed & Key Arrays depends on ECU  
  67.   byte      gSeedArray[2];  
  68.   dword     gSeedArraySize   = 4;  
  69.   char      gVariant[9]    = "Variant1";  
  70.   char      gOption[7]     = "option";  
  71.   dword     gMaxKeyArraySize = 4;  
  72.   dword     gActualSize  = 0;  
  73.      
  74.   byte      request_seed[2]={0x27,0x01};  
  75.   byte      send_key[6]={0x27,0x02,0xAA,0xAA,0xAA,0xAA};  
  76.     
  77.   byte      const_secu_flash[4]={};           //security const number for level flash for BCM  
  78.   byte      const_secu_level1[4]={};          //security const number for level 1 for BCM  
  79.   byte      const_secu_flash_rfcm[4]={};           //security const number for level flash for BCM  
  80.     
  81.   byte      seed[4]={0xAA,0xAA,0xAA,0xAA};                       //store the seed received from server  
  82.   byte      _key[4]={0xAA,0xAA,0xAA,0xAA};                       //store the key generated by tester  
  83.   int       i=0;  
  84.     
  85.   request_seed[ 1 ] = security_level;send_key[ 1 ] = security_level + 0x01;  
  86.   OSEKTL_DataReq(request_seed,elcount(request_seed));         
  87.   if(wait_server_response(request_seed,timeout)!=0){  
  88.     write("fail to retrive seed while unlocking ECU");  
  89.     return -1;  
  90.   }  
  91.     
  92.   for(i=0;i<seed_szie;++i){  
  93.     seed[i]=rxBuffer[i+2];  
  94.   }  
  95.     
  96.   gSeedArraySize = seed_szie;gMaxKeyArraySize = seed_szie;  
  97.   //generate_key(const_secu_flash_rfcm,seed,_key);  
  98.   diagSetTarget(ecu_name);  
  99.   DiagGenerateKeyFromSeed(seed, gSeedArraySize, security_level, gVariant, gOption, _key, gMaxKeyArraySize, gActualSize);  
  100.     
  101.   for(i=0;i<gActualSize;++i){  
  102.     send_key[i+2]=_key[i];  
  103.   }  
  104.     
  105.   OSEKTL_DataReq(send_key,2+gActualSize);  
  106.   return wait_server_response(send_key,timeout);  
  107. }  
  108.   
  109. _Diag_GetError (char buffer[])  
  110. {  
  111. //called if error in DiagGenerateKeyFromSeed occurs  
  112. snprintf(gDebugBuffer,elcount(gDebugBuffer),"%s", buffer);  
  113. write("CALLBACK %s", gDebugBuffer);  
  114. }  
  115.   
  116.   
  117. /* 
  118.   routineControl 
  119. */  
  120. int routine_control(byte _routine_control_type,byte _routine_id[],byte data_record[],int data_record_length){  
  121.   byte request[BUFFER_SIZE_1024];  
  122.   int index=0;  
  123.     
  124.   request[0]=0x31;  
  125.   request[1]=_routine_control_type;  
  126.   request[2]=_routine_id[0];  
  127.   request[3]=_routine_id[1];  
  128.     
  129.   for(index=0;index<data_record_length;++index){  
  130.     request[index+4]=data_record[index];  
  131.   }  
  132.     
  133.   OSEKTL_DataReq(request,data_record_length+4);  
  134.     
  135.   return wait_server_response(request,timeout);   
  136. }  
  137.   
  138. /* 
  139.   generate key according to the received seed 
  140. */  
  141. void generate_key(byte const_secu[],byte seed_secu_flash[],byte securityKey[]){  
  142.   byte key1_secu_flash[4]={0x00,0x00,0x00,0x00};  
  143.   byte key2_secu_flash[4]={0x00,0x00,0x00,0x00};  
  144.   int i=0;  
  145.   byte tmp=0x00;  
  146.     
  147.   for(i=0;i<4;++i){  
  148.     key1_secu_flash[i]=seed_secu_flash[i]^const_secu[i];  
  149.   }  
  150.     
  151.   for(i=0;i<2;++i){  
  152.     tmp=seed_secu_flash[i];  
  153.     seed_secu_flash[i]=seed_secu_flash[3-i];  
  154.     seed_secu_flash[3-i]=tmp;  
  155.   }  
  156.     
  157.   for(i=0;i<4;++i){  
  158.     key2_secu_flash[i]=seed_secu_flash[i]^const_secu[i];  
  159.   }  
  160.     
  161.   for(i=0;i<4;++i){  
  162.     securityKey[i]=key1_secu_flash[i]+key2_secu_flash[i];  
  163.   }  
  164. }  
  165.   
  166. /* 
  167.   communicationControl 
  168. */  
  169. int communication_control(byte _control_type,byte _communication_type){  
  170.   byte request[3]={0x28,0x00,0x00};  
  171.     
  172.   request[1]=_control_type;request[2]=_communication_type;  
  173.     
  174.   OSEKTL_DataReq(request,elcount(request));  
  175.   return wait_server_response(request,timeout);  
  176. }  
  177.   
  178.   
  179. /* 
  180.   controlDTCSetting 
  181. */  
  182. int control_dtc_setting(byte _DTC_setting_type){  
  183.   byte request[2]={0x85,0x00};  
  184.     
  185.   request[1]=_DTC_setting_type;  
  186.     
  187.   OSEKTL_DataReq(request,elcount(request));  
  188.   return wait_server_response(request,timeout);  
  189. }  
  190.   
  191. /* 
  192.   tester Present 
  193. */  
  194. int tester_present(byte sub_function){  
  195.   byte request[2]={0x3e,0x00};  
  196.     
  197.   request[1]=sub_function;  
  198.     
  199.   OSEKTL_DataReq(request,elcount(request));  
  200.   return wait_server_response(request,timeout);  
  201. }  
  202.   
  203. /* 
  204.   writeDataByID 
  205. */  
  206. int write_data_by_id(byte did[],byte _data_record[],int _data_record_length){  
  207.   byte request[256];  
  208.   int i=0,_did_length=2;  
  209.     
  210.   request[0]=0x2E;  
  211.     
  212.   for(i=0;i<_did_length;++i){  
  213.     request[1+i]=did[i];  
  214.   }  
  215.     
  216.   for(i=0;i<_data_record_length;++i){  
  217.     request[1+_did_length+i]=_data_record[i];  
  218.   }  
  219.     
  220.   OSEKTL_DataReq(request,1+_did_length+_data_record_length);  
  221.   return wait_server_response(request,timeout);  
  222. }  
  223.   
  224. /* 
  225.   requestDownload 
  226. */  
  227. int request_download(byte _memory_address[],int _memory_address_length,byte _memory_size[],int __memory_size_length){  
  228.   byte request[256];  
  229.   int i=0;  
  230.     
  231.   request[0]=0x34;request[1]=0x00;request[2]=0x44;  
  232.     
  233.   for(i=0;i<_memory_address_length;++i){  
  234.     request[3+i]=_memory_address[i];  
  235.   }  
  236.     
  237.   for(i=0;i<__memory_size_length;++i){  
  238.     request[3+_memory_address_length+i]=_memory_size[i];  
  239.   }  
  240.     
  241.   OSEKTL_DataReq(request,3+_memory_address_length+__memory_size_length);  
  242.   return wait_server_response(request,timeout);  
  243. }  
  244.   
  245. /* 
  246.   tansferData 
  247. */  
  248. int transfer_data(byte _block_sequence,byte _upload_data[],int _upload_data_length){  
  249.   byte request[BUFFER_SIZE_2048];  
  250.   int i=0 , status = 0;  
  251.     
  252.   request[0]=0x36;request[1]=_block_sequence;  
  253.     
  254.   for(i=0;i<_upload_data_length;++i){  
  255.     request[2+i]=_upload_data[i];  
  256.   }  
  257.     
  258.   OSEKTL_DataReq(request,_upload_data_length+2);  
  259.   status = wait_server_response(request,timeout);  
  260.     
  261.   return status;  
  262. }  
  263.   
  264. /* 
  265.   requstTransferExit 
  266. */  
  267. int request_transfer_exit(){  
  268.   byte request[1]={0x37};  
  269.   
  270.   OSEKTL_DataReq(request,elcount(request));  
  271.   return wait_server_response(request,timeout);  
  272. }  
  273.   
  274. int read_data_by_id(byte did[]){  
  275.   byte request[3]={0x22,0x00,0x00};  
  276.     
  277.   request[1]=did[0];  
  278.   request[2]=did[1];  
  279.     
  280.   OSEKTL_DataReq(request,elcount(request));  
  281.   return wait_server_response(request,timeout);  
  282. }  
  283.   
  284. OSEKTL_FirstFrameIndication( long sourceadr, long destadr, long rxCount )  
  285. {  
  286.   /* Print message to write window */  
  287.   //write("CAPL: %s: FF indication called, SA= 0x%02lx, TA= 0x%02lx, RxCount = %ld (AE=%d)", gECU, sourceadr, destadr, rxCount, OSEKTL_GetRecentAE());  
  288. }  
  289.   
  290. //error handle  
  291. OSEKTL_ErrorInd(int error)  
  292. {  
  293.   switch (error)  
  294.   {  
  295.     case 1:     write("----CAPL: Error (%d): Timeout while waiting for CF", error);     break;  
  296.     case 2:     write("----CAPL: Error (%d): Timeout while waiting for FC", error);     break;  
  297.     case 3:     write("----CAPL: Error (%d): Wrong Sequence Number", error);            break;  
  298.     case 4:     write("----CAPL: Error (%d): TP_DLL busy", error);                      break;  
  299.     case 5:     write("----CAPL: Error (%d): Unexpected PDU", error);stop();                   break;  
  300.     case 6:     write("----CAPL: Error (%d): Timeout while waiting for Tx-Ack", error); break;  
  301.     case 7:     write("----CAPL: Error (%d): WFT Overrun", error);                      break;  
  302.     case 8:     write("----CAPL: Error (%d): Buffer overflow", error);                  break;  
  303.     case 9:     write("----CAPL: Error (%d): Wrong parameter", error);                      break;      
  304.     default:    write("----CAPL: Error (%d): unknown error", error);                    break;  
  305.   }  
  306. }  
  307.   
  308. //request confirm  
  309. OSEKTL_DataCon(long status)  
  310. {  
  311.   if (status != 0)   
  312.   {  
  313.       //write("CAPL: %s: data sent using normal addressing", gECU);  
  314.   }  
  315.   else  
  316.   {  
  317.     write("----CAPL: %s: tx error, status is %d", gECU, status);   
  318.   }  
  319. }  
  320.   
  321. OSEKTL_DataInd( long rxCount )  
  322. {  
  323.   dword glhandle=0;  
  324.     
  325.   /* Get received data */  
  326.   OSEKTL_GetRxData( rxBuffer, 4095 );  
  327.   rxBufferLen=rxCount;  
  328.     
  329.   //signal response received  
  330.   TestSupplyTextEvent(wait_rsp_text_event);  
  331. }  
  332.   
  333. //process will suspend for tTime ms to wait for response  
  334. int wait_server_response(byte request[],dword _tTime){  
  335.   long status=0;  
  336.   int result=0;  
  337.   long flag=5;  
  338.     
  339.   flag=2;result=0;status=0;  
  340.     
  341.   //loop while response pending  
  342.   while(flag>=0)          
  343.   {  
  344.     status=testWaitForTextEvent(wait_rsp_text_event,_tTime);  
  345.     if(status<0){  
  346.       write("service %x:fail to wait server response",request[0]);  
  347.       return -1;  
  348.     }else if(status==0){  
  349.       write("service %x:timeout while waiting for server\'s response",request[0]);  
  350.       return -1;  
  351.     }  
  352.       
  353.     result=checkResponse(request);  
  354.       
  355.     if(result==-3){  
  356.       write("response pending");  
  357.       flag=5;  
  358.     }  
  359.       
  360.     if(result==-2){  
  361.       write("Warning:unexpected positive response");  
  362.       flag--;  
  363.     }  
  364.       
  365.     if(result==-1){  
  366.       write("service %x:negative response received",request[0]);  
  367.       break;  
  368.     }  
  369.       
  370.     if(result==0){  
  371.       //write("positive response received\n");  
  372.       break;  
  373.     }  
  374.   }  
  375.   
  376.   if(result<0){    
  377.     msgBeep(5);  
  378.     return -1;  
  379.   }  
  380.     
  381.   return 0;  
  382. }  
  383.   
  384. /* 
  385.   check response 
  386.   return 0 if positive response received 
  387.   otherwise return -1,-2,-3,0 
  388.   */  
  389. int checkResponse(byte request[]){  
  390.   if(rxBufferLen<=0){  
  391.     write("Error:empty response reveived\n");  
  392.     return -1;  
  393.   }  
  394.   else{   
  395.     if(rxBuffer[0]==request[0]+0x40){  
  396.       //write("positive response received\n");  
  397.       return 0;  
  398.     }else if(rxBuffer[0]!=0x7F&&rxBuffer[0]!=(rxBuffer[0]+0x40)){  
  399.       //unexpected positive response  
  400.       return -2;  
  401.     }  
  402.     else if(rxBuffer[0]==0x7F&&rxBuffer[1]==request[0]){   
  403.       if(rxBuffer[2]!=0x78)  
  404.       {  
  405.         //write("Error:negative response received\n");  
  406.         return -1;  
  407.       }else{  
  408.        //response pending  
  409.        return -3;  
  410.       }  
  411.     }  
  412.   }  
  413.   return 0;  
  414. }  


  • 40
    点赞
  • 322
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值