Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
gmlan.cpp
- Committer:
- Just4pLeisure
- Date:
- 2015-04-25
- Revision:
- 5:1775b4b13232
- Parent:
- 4:682d96ff6d79
File content as of revision 5:1775b4b13232:
#include "gmlan.h" Timer GMLANtimer; void GMLANTesterPresentAll() { char GMLANMsg[] = GMLANTesterPresentFunctional; can_send_timeout(GMLANALLNODES, GMLANMsg, 3, GMLANPTCT); ACTIVITYLEDON; } void GMLANTesterPresent(uint32_t ReqID, uint32_t RespID) { char GMLANMsg[] = GMLANTesterPresentPhysical; can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT); can_wait_timeout(RespID, GMLANMsg, 2, GMLANPTCT); ACTIVITYLEDON; } // All steps needed in preparation for using a bootloader ('Utility File' in GMLAN parlance) bool GMLANprogrammingSetupProcess(uint32_t ReqID, uint32_t RespID) { GMLANTesterPresent(ReqID, RespID); printf("Starting Diagnostic session\r\n"); if (!GMLANinitiateDiagnostic(ReqID, RespID, GMLANdisableAllDTCs)) { printf("Unable to start Diagnostic session\r\n"); return FALSE; } printf("Disabling Normal Communincation Messages\r\n"); if (!GMLANdisableNormalCommunication(ReqID, RespID)) { printf("Unable to tell T8 to disable normal communication messages\r\n"); return FALSE; } printf("Report Programmed State\r\n"); if (!GMLANReportProgrammedState(ReqID, RespID)) { printf("Unable to determine ECU programmed state\r\n"); } printf("Requesting program mode\r\n"); if (!GMLANProgrammingMode(ReqID, RespID, GMLANRequestProgrammingNormal)) { printf("Unable to request programming mode\r\n"); return FALSE; } printf("Starting program session\r\n"); if (!GMLANProgrammingMode(ReqID, RespID, GMLANEnableProgrammingMode)) { printf("Unable to start program session\r\n"); return FALSE; } wait_ms(500); // was 5 return TRUE; } // All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) bool GMLANprogrammingUtilityFileProcess(uint32_t ReqID, uint32_t RespID, const uint8_t UtilityFile[]) { uint16_t i = 0, j = 0, k = 0; uint32_t StartAddress = 0x102400; uint16_t txpnt = 0; char iFrameNumber = 0x21; char GMLANMsg[8]; // GMLANTesterPresent(ReqID, RespID); GMLANtimer.start(); printf("Waiting for Permission to send bootloader\r\n"); wait_ms(500); if (!GMLANRequestDownload(ReqID, RespID, GMLANRequestDownloadModeNormal)) { printf("Unable to request Bootloader Upload\r\n"); return FALSE; } printf("Sending Bootloader\r\n"); printf(" 0.00 %% complete.\r"); // for (i=0; i<0x46; i++) { if (!GMLANDataTransferFirstFrame(ReqID, RespID, 0xF0, GMLANDOWNLOAD, StartAddress)) { printf("Unable to start Bootloader Upload\r\n"); return FALSE; } iFrameNumber = 0x21; for (j=0; j < 0x22; j++) { GMLANMsg[0] = iFrameNumber; for (k=1; k<8; k++) GMLANMsg[k] = UtilityFile[txpnt++]; if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) { printf("Unable to send Bootloader\r\n"); return FALSE; } ++iFrameNumber &= 0x2F; wait_ms(2); // was 2 } if (!GMLANDataTransferBlockAcknowledge(RespID)) return FALSE; if (GMLANtimer.read_ms() > 2000) { GMLANTesterPresent(ReqID, RespID); GMLANtimer.reset(); } StartAddress += 0xea; printf("%6.2f\r", 100*(float)txpnt/(float)(16384+(70*4)) ); } wait_ms(1); if (!GMLANDataTransferFirstFrame(ReqID, RespID, 0x0A, GMLANDOWNLOAD, StartAddress)) { printf("Unable to finish Bootloader Upload\r\n"); return FALSE; } iFrameNumber = 0x21; GMLANMsg[0] = iFrameNumber; for (k=0; k<7; k++) { GMLANMsg[k+1] = UtilityFile[txpnt++]; } if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) { printf("Unable to finish sending Bootloader\r\n"); return FALSE; } if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; printf("%6.2f\r\n", (float)100 ); printf("Starting the bootloader\r\n"); if (!GMLANDataTransfer(ReqID, RespID, 0x06, GMLANEXECUTE, 0x00102460)) { printf("Unable to start the Bootloader\r\n"); return FALSE; } wait_ms(500); // was 100 return TRUE; } bool GMLANinitiateDiagnostic(uint32_t ReqID, uint32_t RespID, char level) { char GMLANMsg[] = GMLANinitiateDiagnosticOperation; GMLANMsg[2] = level; if (!can_send_timeout(ReqID, GMLANMsg, 3, GMLANPTCT)) return FALSE; if (ReqID == T8USDTREQID) return TRUE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x10 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x10 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x50) ? TRUE : FALSE; } bool GMLANdisableNormalCommunication(uint32_t ReqID, uint32_t RespID) { char GMLANMsg[] = GMLANdisableCommunication; if (!can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT)) return FALSE; if (ReqID == T8USDTREQID) return TRUE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x28 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x28 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x68) ? TRUE : FALSE; } bool GMLANReportProgrammedState(uint32_t ReqID, uint32_t RespID) { char GMLANMsg[] = GMLANReportProgrammed; if (!can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA2 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA2 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x02 && GMLANMsg[1] == 0xE2) ? TRUE : FALSE; } bool GMLANProgrammingMode(uint32_t ReqID, uint32_t RespID, char mode) { char GMLANMsg[] = GMLANProgramming; GMLANMsg[2] = mode; if (!can_send_timeout(ReqID, GMLANMsg, 3, GMLANPTCT)) return FALSE; if (mode == GMLANEnableProgrammingMode) return TRUE; // No response expected when enabling program mode if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA5 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA5 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0xE5) ? TRUE : FALSE; } bool GMLANSecurityAccessRequest(uint32_t ReqID, uint32_t RespID, char level, uint16_t& seed) { char GMLANMsg[] = GMLANSecurityAccessSeed; GMLANMsg[2] = level; if (!can_send_timeout(ReqID, GMLANMsg, 3, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; seed = GMLANMsg[3] << 8 | GMLANMsg[4]; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x04 && GMLANMsg[1] == 0x67 && GMLANMsg[2] == level) ? TRUE : FALSE; } bool GMLANSecurityAccessSendKey(uint32_t ReqID, uint32_t RespID, char level, uint16_t key) { char GMLANMsg[] = GMLANSecurityAccessKey; GMLANMsg[2] = level+1; GMLANMsg[3] = (key >> 8) & 0xFF; GMLANMsg[4] = key & 0xFF; if (!can_send_timeout(ReqID, GMLANMsg, 5, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x27 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x02 && GMLANMsg[1] == 0x67 && GMLANMsg[2] == level+1) ? TRUE : FALSE; } bool GMLANRequestDownload(uint32_t ReqID, uint32_t RespID, char dataFormatIdentifier) { char GMLANMsg[] = GMLANRequestDownloadMessage; GMLANMsg[2] = dataFormatIdentifier; if (!can_send_timeout(ReqID, GMLANMsg, 7, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x34 && GMLANMsg[3] == 0x78) { printf("Waiting\r\n"); GMLANTesterPresent(T8REQID, T8RESPID); if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; } if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x34 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x74) ? TRUE : FALSE; } bool GMLANDataTransfer(uint32_t ReqID, uint32_t RespID, char length, char function, uint32_t address) { char GMLANMsg[8]; GMLANMsg[0] = length; GMLANMsg[1] = 0x36; GMLANMsg[2] = function; GMLANMsg[3] = (char) (address >> 24); GMLANMsg[4] = (char) (address >> 16); GMLANMsg[5] = (char) (address >> 8); GMLANMsg[6] = (char) (address); GMLANMsg[7] = 0xaa; if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x76) ? TRUE : FALSE; } bool GMLANDataTransferFirstFrame(uint32_t ReqID, uint32_t RespID, char length, char function, uint32_t address) { char GMLANMsg[8]; GMLANMsg[0] = 0x10; GMLANMsg[1] = length; GMLANMsg[2] = 0x36; GMLANMsg[3] = function; GMLANMsg[4] = (char) (address >> 24); GMLANMsg[5] = (char) (address >> 16); GMLANMsg[6] = (char) (address >> 8); GMLANMsg[7] = (char) (address); if (!can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x30 && GMLANMsg[1] == 0x00 && GMLANMsg[2] == 0x00) ? TRUE : FALSE; } bool GMLANDataTransferConsecutiveFrame(uint32_t ReqID, char framenumber, char data[8]) { char GMLANMsg[8]; GMLANMsg[0] = framenumber; for (char k = 0; k < 7; k++ ) GMLANMsg[k+1] = data[k]; return (can_send_timeout(ReqID, GMLANMsg, 8, GMLANPTCT)) ? TRUE : FALSE; } bool GMLANDataTransferBlockAcknowledge(uint32_t RespID) { char GMLANMsg[8]; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) { printf("\r\nI did not receive a block acknowledge message\r\n"); return FALSE; } if (GMLANMsg[0] != 0x01 && GMLANMsg[1] != 0x76) { while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) { printf("\r\nI'm waiting for a block acknowledge message\r\n"); if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) { printf("I did not receive a block acknowledge message after enhanced timeout\r\n"); return FALSE; } } if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) { GMLANShowReturnCode(GMLANMsg[3]); return FALSE; } if (GMLANMsg[0] != 0x01 && GMLANMsg[1] != 0x76) { printf("\r\nEXITING due to an unexpected CAN message\r\n"); return FALSE; } } return TRUE; } bool GMLANReturnToNormalMode(uint32_t ReqID, uint32_t RespID) { char GMLANMsg[] = GMLANReturnToNormalModeMessage; if (!can_send_timeout(ReqID, GMLANMsg, 2, GMLANPTCT)) return FALSE; if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCT)) return FALSE; while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x20 && GMLANMsg[3] == 0x78) if (!can_wait_timeout(RespID, GMLANMsg, 8, GMLANPTCTENHANCED)) return FALSE; if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x20 ) GMLANShowReturnCode(GMLANMsg[3]); return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x60) ? TRUE : FALSE; } void GMLANShowReturnCode(char returnCode) { switch (returnCode) { case 0x11 : printf("0x11 - ServiceNotSupported\r\n"); break; case 0x12 : printf("0x12 - SubFunctionNotSupported-InvalidFormat\r\n"); break; case 0x22 : printf("0x22 - ConditionsNotCorrectOrRequestSequenceError\r\n"); break; case 0x31 : printf("0x31 - RequestOutOfRange\r\n"); break; case 0x35 : printf("0x35 - InvalidKey\r\n"); break; case 0x36 : printf("0x36 - ExceededNumberOfAttempts, ECU is now locked!\r\n"); break; case 0x37 : printf("0x37 - RequiredTimeDelayNotExpired\r\n"); break; case 0x78 : printf("0x78 - RequestCorrectlyReceived-ResponsePending\r\n"); break; case 0x81 : printf("0x81 - SchedulerFull\r\n"); break; case 0x83 : printf("0x83 - VoltageOutOfRangeFault\r\n"); break; case 0x85 : printf("0x85 - GeneralProgrammingFailure\r\n"); break; case 0x99 : printf("0x99 - ReadyForDownload-DTCStored\r\n"); break; case 0xE3 : printf("0xE3 - DeviceControlLimitsExceeded\r\n"); break; default : printf("Unknown failure Return Code ?!?\r\n"); } }