Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Diff: gmlan.cpp
- Revision:
- 4:682d96ff6d79
- Child:
- 5:1775b4b13232
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gmlan.cpp Wed Sep 11 11:55:51 2013 +0000 @@ -0,0 +1,458 @@ +#include "gmlan.h" + +void GMLANTesterPresentAll() +{ + char GMLANMsg[] = GMLANTesterPresentFunctional; + can_send_timeout(GMLANALLNODES, GMLANMsg, 3, GMLANPTCT); + ACTIVITYLEDON; +} + +void GMLANTesterPresentT8() +{ + char GMLANMsg[] = GMLANTesterPresentPhysical; + can_send_timeout(T8RequestId, GMLANMsg, 8, GMLANPTCT); + can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT); + ACTIVITYLEDON; +} + +// All steps needed in preparation for using a bootloader ('Utility File' in GMLAN parlance) +bool GMLANprogrammingSetupProcess() +{ + printf("Starting Diagnostic session\r\n"); + if (!GMLANinitiateDiagnostic(GMLANdisableAllDTCs)) { + printf("Unable to start Diagnostic session\r\n"); + return FALSE; + } + printf("Disabling Normal Communincation Messages\r\n"); + if (!GMLANdisableNormalCommunication()) { + printf("Unable to tell T8 to disable normal communication messages\r\n"); + return FALSE; + } + printf("Report Programmed State\r\n"); + if (!GMLANReportProgrammedState()) { + printf("Unable to determine ECU programmed state\r\n"); + return FALSE; + } + printf("Requesting program mode\r\n"); + if (!GMLANProgrammingMode(GMLANRequestProgrammingNormal)) { + printf("Unable to request programming mode\r\n"); + return FALSE; + } + printf("Starting program session\r\n"); + if (!GMLANProgrammingMode(GMLANEnableProgrammingMode)) { + printf("Unable to start program session\r\n"); + return FALSE; + } + return TRUE; +} + + +// All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) +bool GMLANprogrammingUtilityFileProcess(char UtilityFile[]) +{ + uint16_t i = 0, j = 0, k = 0; + uint32_t StartAddress = 0x102400; + uint16_t txpnt = 0; + char iFrameNumber = 0x21; + char GMLANMsg[8]; + //char BootLoader[] = T8Bootloader; +// + printf("Waiting for Permission to send bootloader\r\n"); + if (!GMLANRequestDownload(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(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++]; +#ifdef DEBUG + for (k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 8, GMLANPTCT)) { + printf("Unable to send Bootloader\r\n"); + return FALSE; + } + ++iFrameNumber &= 0x2F; + wait_ms(1); +// wait_us(500); + } + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) { + printf("I didn't receive a block acknowledge message\r\n"); + return FALSE; + } + while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 && GMLANMsg[3] == 0x78) { + printf("I'm waiting for a BootLoader Block to upload\r\n"); + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) { + printf("I didn't receive a block acknowledge message after enhanced timeout\r\n"); + return FALSE; + } + } +#ifdef DEBUG + for (k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) { + GMLANShowReturnCode(GMLANMsg[3]); + return FALSE; + } + if (GMLANMsg[0] != 0x01 && GMLANMsg[1] != 0x76) { + printf("EXITING due to an unexpected CAN message\r\n"); + return FALSE; + } + GMLANTesterPresentT8(); + ACTIVITYLEDON; + StartAddress += 0xea; + printf("%6.2f\r", 100*(float)txpnt/(float)(16384+(70*4)) ); + } + wait_ms(1); + if (!GMLANDataTransferFirstFrame(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(T8RequestId, GMLANMsg, 8, GMLANPTCT)) { + printf("Unable to finish sending Bootloader\r\n"); + return FALSE; + } + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; +#ifdef DEBUG + for (k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + printf("%6.2f\r\n", (float)100 ); + printf("Starting the bootloader\r\n"); + if (!GMLANDataTransfer(0x06, GMLANEXECUTE, 0x00102460)) { + printf("Unable to start the Bootloader\r\n"); + return FALSE; + } + wait_ms(500); + return TRUE; +} + +bool GMLANinitiateDiagnostic(char level) +{ + char GMLANMsg[] = GMLANinitiateDiagnosticOperation; + GMLANMsg[2] = level; + if (!can_send_timeout(T8RequestId, GMLANMsg, 3, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x10 && GMLANMsg[3] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x10 ) + GMLANShowReturnCode(GMLANMsg[3]); + return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x50) ? TRUE : FALSE; +} + + +bool GMLANdisableNormalCommunication() +{ + char GMLANMsg[] = GMLANdisableCommunication; + if (!can_send_timeout(T8RequestId, GMLANMsg, 2, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x28 ) + GMLANShowReturnCode(GMLANMsg[3]); + return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x68) ? TRUE : FALSE; +} + + +bool GMLANReportProgrammedState() +{ + char GMLANMsg[] = GMLANReportProgrammed; + if (!can_send_timeout(T8RequestId, GMLANMsg, 2, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA2 ) + GMLANShowReturnCode(GMLANMsg[3]); + return (GMLANMsg[0] == 0x02 && GMLANMsg[1] == 0xE2) ? TRUE : FALSE; +} + + +bool GMLANProgrammingMode(char mode) +{ + char GMLANMsg[] = GMLANProgramming; + GMLANMsg[2] = mode; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 3, GMLANPTCT)) + return FALSE; + if (mode == GMLANEnableProgrammingMode) + return TRUE; // No response expected when enabling program mode + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0xA5 ) + GMLANShowReturnCode(GMLANMsg[3]); + return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0xE5) ? TRUE : FALSE; +} + +bool GMLANSecurityAccessRequest(char level, uint16_t& seed) +{ + char GMLANMsg[] = GMLANSecurityAccessSeed; + GMLANMsg[2] = level; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 3, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + 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(char level, uint16_t key) +{ + char GMLANMsg[] = GMLANSecurityAccessKey; + GMLANMsg[2] = level+1; + GMLANMsg[3] = (key >> 8) & 0xFF; + GMLANMsg[4] = key & 0xFF; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 5, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + 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(char dataFormatIdentifier) +{ + char GMLANMsg[] = GMLANRequestDownloadMessage; + GMLANMsg[2] = dataFormatIdentifier; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 7, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; +// while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + while (GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x34 && GMLANMsg[3] == 0x78) { + printf("Erasing\r\n"); + GMLANTesterPresentT8(); + ACTIVITYLEDON; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; + } +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x34 ) + GMLANShowReturnCode(GMLANMsg[3]); + return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x74) ? TRUE : FALSE; +} + + +bool GMLANDataTransfer(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; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x36 ) + GMLANShowReturnCode(GMLANMsg[3]); + return (GMLANMsg[0] == 0x01 && GMLANMsg[1] == 0x76) ? TRUE : FALSE; +} + + +bool GMLANDataTransferFirstFrame(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); +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if (!can_send_timeout(T8RequestId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + 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(char framenumber, char data[7]) +{ + char GMLANMsg[8]; + GMLANMsg[0] = framenumber; + for (char k = 0; k < 7; k++ ) + GMLANMsg[k+1] = data[k]; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + return (can_send_timeout(T8RequestId, GMLANMsg, 8, GMLANPTCT)) ? TRUE : FALSE; +} + +bool GMLANReturnToNormalMode() +{ + char GMLANMsg[] = GMLANRetrunToNormalModeMessage; + if (!can_send_timeout(T8RequestId, GMLANMsg, 2, GMLANPTCT)) + return FALSE; + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCT)) + return FALSE; + while (GMLANMsg[0] == 0x7F && GMLANMsg[2] == 0x78) + if (!can_wait_timeout(T8ResponseId, GMLANMsg, 8, GMLANPTCTENHANCED)) + return FALSE; +#ifdef DEBUG + for (char k = 0; k < 8; k++ ) printf("0x%02X ", GMLANMsg[k] ); + printf("\r\n"); +#endif + if ( GMLANMsg[0] == 0x03 && GMLANMsg[1] == 0x7F && GMLANMsg[2] == 0x28 ) + 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"); + } +}