Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Embed:
(wiki syntax)
Show/hide line numbers
gmlan.cpp
00001 #include "gmlan.h" 00002 00003 Timer GMLANtimer; 00004 00005 00006 void GMLANTesterPresentAll() 00007 { 00008 char GMLANMsg[] = GMLANTesterPresentFunctional; 00009 can_send_timeout(GMLANALLNODES, GMLANMsg, 3, GMLANPTCT); 00010 ACTIVITYLEDON; 00011 } 00012 00013 void GMLANTesterPresent(uint32_t ReqID, uint32_t RespID) 00014 { 00015 char GMLANMsg[] = GMLANTesterPresentPhysical; 00016 can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT); 00017 can_wait_timeout(RespID, GMLANMsg, 2, GMLANPTCT); 00018 ACTIVITYLEDON; 00019 } 00020 00021 // All steps needed in preparation for using a bootloader ('Utility File' in GMLAN parlance) 00022 bool GMLANprogrammingSetupProcess(uint32_t ReqID, uint32_t RespID) 00023 { 00024 GMLANTesterPresent(ReqID, RespID); 00025 printf("Starting Diagnostic session\r\n"); 00026 if (!GMLANinitiateDiagnostic(ReqID, RespID, GMLANdisableAllDTCs)) { 00027 printf("Unable to start Diagnostic session\r\n"); 00028 return FALSE; 00029 } 00030 printf("Disabling Normal Communincation Messages\r\n"); 00031 if (!GMLANdisableNormalCommunication(ReqID, RespID)) { 00032 printf("Unable to tell T8 to disable normal communication messages\r\n"); 00033 return FALSE; 00034 } 00035 printf("Report Programmed State\r\n"); 00036 if (!GMLANReportProgrammedState(ReqID, RespID)) { 00037 printf("Unable to determine ECU programmed state\r\n"); 00038 } 00039 printf("Requesting program mode\r\n"); 00040 if (!GMLANProgrammingMode(ReqID, RespID, GMLANRequestProgrammingNormal)) { 00041 printf("Unable to request programming mode\r\n"); 00042 return FALSE; 00043 } 00044 printf("Starting program session\r\n"); 00045 if (!GMLANProgrammingMode(ReqID, RespID, GMLANEnableProgrammingMode)) { 00046 printf("Unable to start program session\r\n"); 00047 return FALSE; 00048 } 00049 wait_ms(500); // was 5 00050 return TRUE; 00051 } 00052 00053 00054 // All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) 00055 bool GMLANprogrammingUtilityFileProcess(uint32_t ReqID, uint32_t RespID, const uint8_t UtilityFile[]) 00056 { 00057 uint16_t i = 0, j = 0, k = 0; 00058 uint32_t StartAddress = 0x102400; 00059 uint16_t txpnt = 0; 00060 char iFrameNumber = 0x21; 00061 char GMLANMsg[8]; 00062 // 00063 GMLANTesterPresent(ReqID, RespID); 00064 GMLANtimer.start(); 00065 printf("Waiting for Permission to send bootloader\r\n"); 00066 wait_ms(500); 00067 if (!GMLANRequestDownload(ReqID, RespID, GMLANRequestDownloadModeNormal)) { 00068 printf("Unable to request Bootloader Upload\r\n"); 00069 return FALSE; 00070 } 00071 printf("Sending Bootloader\r\n"); 00072 printf(" 0.00 %% complete.\r"); 00073 // 00074 for (i=0; i<0x46; i++) { 00075 if (!GMLANDataTransferFirstFrame(ReqID, RespID, 0xF0, GMLANDOWNLOAD, StartAddress)) { 00076 printf("Unable to start Bootloader Upload\r\n"); 00077 return FALSE; 00078 } 00079 iFrameNumber = 0x21; 00080 for (j=0; j < 0x22; j++) { 00081 GMLANMsg[0] = iFrameNumber; 00082 for (k=1; k<8; k++) 00083 GMLANMsg[k] = UtilityFile[txpnt++]; 00084 if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) { 00085 printf("Unable to send Bootloader\r\n"); 00086 return FALSE; 00087 } 00088 ++iFrameNumber &= 0x2F; 00089 wait_ms(2); // was 2 00090 } 00091 if (!GMLANDataTransferBlockAcknowledge(RespID)) 00092 return FALSE; 00093 if (GMLANtimer.read_ms() > 2000) { 00094 GMLANTesterPresent(ReqID, RespID); 00095 GMLANtimer.reset(); 00096 } 00097 StartAddress += 0xea; 00098 printf("%6.2f\r", 100*(float)txpnt/(float)(16384+(70*4)) ); 00099 } 00100 wait_ms(1); 00101 if (!GMLANDataTransferFirstFrame(ReqID, RespID, 0x0A, GMLANDOWNLOAD, StartAddress)) { 00102 printf("Unable to finish Bootloader Upload\r\n"); 00103 return FALSE; 00104 } 00105 iFrameNumber = 0x21; 00106 GMLANMsg[0] = iFrameNumber; 00107 for (k=0; k<7; k++) { 00108 GMLANMsg[k+1] = UtilityFile[txpnt++]; 00109 } 00110 if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) { 00111 printf("Unable to finish sending Bootloader\r\n"); 00112 return FALSE; 00113 } 00114 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00115 return FALSE; 00116 printf("%6.2f\r\n", (float)100 ); 00117 printf("Starting the bootloader\r\n"); 00118 if (!GMLANDataTransfer(ReqID, RespID, 0x06, GMLANEXECUTE, 0x00102460)) { 00119 printf("Unable to start the Bootloader\r\n"); 00120 return FALSE; 00121 } 00122 wait_ms(500); // was 100 00123 return TRUE; 00124 } 00125 00126 bool GMLANinitiateDiagnostic(uint32_t ReqID, uint32_t RespID, char level) 00127 { 00128 char GMLANMsg[] = GMLANinitiateDiagnosticOperation; 00129 GMLANMsg[2] = level; 00130 if (!can_send_timeout(ReqID, GMLANMsg, 3, GMLANPTCT)) 00131 return FALSE; 00132 if (ReqID == T8USDTREQID) return TRUE; 00133 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00134 return FALSE; 00135 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x10 && GMLANMsg[3] == 0x78) 00136 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00137 return FALSE; 00138 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x10 ) 00139 GMLANShowReturnCode(GMLANMsg[3]); 00140 return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x50) ? TRUE : FALSE; 00141 } 00142 00143 00144 bool GMLANdisableNormalCommunication(uint32_t ReqID, uint32_t RespID) 00145 { 00146 char GMLANMsg[] = GMLANdisableCommunication; 00147 if (!can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT)) 00148 return FALSE; 00149 if (ReqID == T8USDTREQID) return TRUE; 00150 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00151 return FALSE; 00152 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x28 && GMLANMsg[3] == 0x78) 00153 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00154 return FALSE; 00155 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x28 ) 00156 GMLANShowReturnCode(GMLANMsg[3]); 00157 return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x68) ? TRUE : FALSE; 00158 } 00159 00160 00161 bool GMLANReportProgrammedState(uint32_t ReqID, uint32_t RespID) 00162 { 00163 char GMLANMsg[] = GMLANReportProgrammed; 00164 if (!can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT)) 00165 return FALSE; 00166 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00167 return FALSE; 00168 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA2 && GMLANMsg[3] == 0x78) 00169 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00170 return FALSE; 00171 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA2 ) 00172 GMLANShowReturnCode(GMLANMsg[3]); 00173 return (GMLANMsg[0] == 0x02 && GMLANMsg[1] == 0xE2) ? TRUE : FALSE; 00174 } 00175 00176 00177 bool GMLANProgrammingMode(uint32_t ReqID, uint32_t RespID, char mode) 00178 { 00179 char GMLANMsg[] = GMLANProgramming; 00180 GMLANMsg[2] = mode; 00181 if (!can_send_timeout(ReqID, GMLANMsg, 3, GMLANPTCT)) 00182 return FALSE; 00183 if (mode == GMLANEnableProgrammingMode) 00184 return TRUE; // No response expected when enabling program mode 00185 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00186 return FALSE; 00187 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA5 && GMLANMsg[3] == 0x78) 00188 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00189 return FALSE; 00190 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA5 ) 00191 GMLANShowReturnCode(GMLANMsg[3]); 00192 return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0xE5) ? TRUE : FALSE; 00193 } 00194 00195 bool GMLANSecurityAccessRequest(uint32_t ReqID, uint32_t RespID, char level, uint16_t& seed) 00196 { 00197 char GMLANMsg[] = GMLANSecurityAccessSeed; 00198 GMLANMsg[2] = level; 00199 if (!can_send_timeout(ReqID, GMLANMsg, 3, GMLANPTCT)) 00200 return FALSE; 00201 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00202 return FALSE; 00203 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 && GMLANMsg[3] == 0x78) 00204 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00205 return FALSE; 00206 seed = GMLANMsg[3] << 8 | GMLANMsg[4]; 00207 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 ) 00208 GMLANShowReturnCode(GMLANMsg[3]); 00209 return (GMLANMsg[0] == 0x04 && GMLANMsg[1] == 0x67 && GMLANMsg[2] == level) ? TRUE : FALSE; 00210 } 00211 00212 bool GMLANSecurityAccessSendKey(uint32_t ReqID, uint32_t RespID, char level, uint16_t key) 00213 { 00214 char GMLANMsg[] = GMLANSecurityAccessKey; 00215 GMLANMsg[2] = level+1; 00216 GMLANMsg[3] = (key >> 8) & 0xFF; 00217 GMLANMsg[4] = key & 0xFF; 00218 if (!can_send_timeout(ReqID, GMLANMsg, 5, GMLANPTCT)) 00219 return FALSE; 00220 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00221 return FALSE; 00222 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 && GMLANMsg[3] == 0x78) 00223 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00224 return FALSE; 00225 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 ) 00226 GMLANShowReturnCode(GMLANMsg[3]); 00227 return (GMLANMsg[0] == 0x02 && GMLANMsg[1] == 0x67 && GMLANMsg[2] == level+1) ? TRUE : FALSE; 00228 } 00229 00230 bool GMLANRequestDownload(uint32_t ReqID, uint32_t RespID, char dataFormatIdentifier) 00231 { 00232 char GMLANMsg[] = GMLANRequestDownloadMessage; 00233 GMLANMsg[2] = dataFormatIdentifier; 00234 if (!can_send_timeout(ReqID, GMLANMsg, 7, GMLANPTCT)) 00235 return FALSE; 00236 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00237 return FALSE; 00238 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x34 && GMLANMsg[3] == 0x78) { 00239 printf("Waiting\r\n"); 00240 GMLANTesterPresent(T8REQID, T8RESPID); 00241 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00242 return FALSE; 00243 } 00244 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x34 ) 00245 GMLANShowReturnCode(GMLANMsg[3]); 00246 return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x74) ? TRUE : FALSE; 00247 } 00248 00249 00250 bool GMLANDataTransfer(uint32_t ReqID, uint32_t RespID, char length, char function, uint32_t address) 00251 { 00252 char GMLANMsg[8]; 00253 GMLANMsg[0] = length; 00254 GMLANMsg[1] = 0x36; 00255 GMLANMsg[2] = function; 00256 GMLANMsg[3] = (char) (address >> 24); 00257 GMLANMsg[4] = (char) (address >> 16); 00258 GMLANMsg[5] = (char) (address >> 8); 00259 GMLANMsg[6] = (char) (address); 00260 GMLANMsg[7] = 0xaa; 00261 if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) 00262 return FALSE; 00263 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00264 return FALSE; 00265 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) 00266 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00267 return FALSE; 00268 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) 00269 GMLANShowReturnCode(GMLANMsg[3]); 00270 return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x76) ? TRUE : FALSE; 00271 } 00272 00273 00274 bool GMLANDataTransferFirstFrame(uint32_t ReqID, uint32_t RespID, char length, char function, uint32_t address) 00275 { 00276 char GMLANMsg[8]; 00277 GMLANMsg[0] = 0x10; 00278 GMLANMsg[1] = length; 00279 GMLANMsg[2] = 0x36; 00280 GMLANMsg[3] = function; 00281 GMLANMsg[4] = (char) (address >> 24); 00282 GMLANMsg[5] = (char) (address >> 16); 00283 GMLANMsg[6] = (char) (address >> 8); 00284 GMLANMsg[7] = (char) (address); 00285 if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) 00286 return FALSE; 00287 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00288 return FALSE; 00289 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) 00290 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00291 return FALSE; 00292 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) 00293 GMLANShowReturnCode(GMLANMsg[3]); 00294 return (GMLANMsg[0] == 0x30 && GMLANMsg[1] == 0x00 && GMLANMsg[2] == 0x00) ? TRUE : FALSE; 00295 } 00296 00297 00298 bool GMLANDataTransferConsecutiveFrame(uint32_t ReqID, char framenumber, char data[8]) 00299 { 00300 char GMLANMsg[8]; 00301 GMLANMsg[0] = framenumber; 00302 for (char k = 0; k < 7; k++ ) 00303 GMLANMsg[k+1] = data[k]; 00304 return (can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) ? TRUE : FALSE; 00305 } 00306 00307 bool GMLANDataTransferBlockAcknowledge(uint32_t RespID) 00308 { 00309 char GMLANMsg[8]; 00310 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) { 00311 printf("\r\nI did not receive a block acknowledge message\r\n"); 00312 return FALSE; 00313 } 00314 if (GMLANMsg[0] != 0x01 && GMLANMsg[1] != 0x76) { 00315 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) { 00316 printf("\r\nI'm waiting for a block acknowledge message\r\n"); 00317 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) { 00318 printf("I did not receive a block acknowledge message after enhanced timeout\r\n"); 00319 return FALSE; 00320 } 00321 } 00322 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) { 00323 GMLANShowReturnCode(GMLANMsg[3]); 00324 return FALSE; 00325 } 00326 if (GMLANMsg[0] != 0x01 && GMLANMsg[1] != 0x76) { 00327 printf("\r\nEXITING due to an unexpected CAN message\r\n"); 00328 return FALSE; 00329 } 00330 } 00331 return TRUE; 00332 } 00333 00334 bool GMLANReturnToNormalMode(uint32_t ReqID, uint32_t RespID) 00335 { 00336 char GMLANMsg[] = GMLANReturnToNormalModeMessage; 00337 if (!can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT)) 00338 return FALSE; 00339 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) 00340 return FALSE; 00341 while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x20 && GMLANMsg[3] == 0x78) 00342 if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) 00343 return FALSE; 00344 if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x20 ) 00345 GMLANShowReturnCode(GMLANMsg[3]); 00346 return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x60) ? TRUE : FALSE; 00347 } 00348 00349 00350 void GMLANShowReturnCode(char returnCode) 00351 { 00352 switch (returnCode) { 00353 case 0x11 : 00354 printf("0x11 - ServiceNotSupported\r\n"); 00355 break; 00356 case 0x12 : 00357 printf("0x12 - SubFunctionNotSupported-InvalidFormat\r\n"); 00358 break; 00359 case 0x22 : 00360 printf("0x22 - ConditionsNotCorrectOrRequestSequenceError\r\n"); 00361 break; 00362 case 0x31 : 00363 printf("0x31 - RequestOutOfRange\r\n"); 00364 break; 00365 case 0x35 : 00366 printf("0x35 - InvalidKey\r\n"); 00367 break; 00368 case 0x36 : 00369 printf("0x36 - ExceededNumberOfAttempts, ECU is now locked!\r\n"); 00370 break; 00371 case 0x37 : 00372 printf("0x37 - RequiredTimeDelayNotExpired\r\n"); 00373 break; 00374 case 0x78 : 00375 printf("0x78 - RequestCorrectlyReceived-ResponsePending\r\n"); 00376 break; 00377 case 0x81 : 00378 printf("0x81 - SchedulerFull\r\n"); 00379 break; 00380 case 0x83 : 00381 printf("0x83 - VoltageOutOfRangeFault\r\n"); 00382 break; 00383 case 0x85 : 00384 printf("0x85 - GeneralProgrammingFailure\r\n"); 00385 break; 00386 case 0x99 : 00387 printf("0x99 - ReadyForDownload-DTCStored\r\n"); 00388 break; 00389 case 0xE3 : 00390 printf("0xE3 - DeviceControlLimitsExceeded\r\n"); 00391 break; 00392 default : 00393 printf("Unknown failure Return Code ?!?\r\n"); 00394 } 00395 }
Generated on Fri Jul 15 2022 00:43:05 by 1.7.2