Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gmlan.cpp Source File

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 }