Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
gmlan.cpp
- Committer:
- Just4pLeisure
- Date:
- 2013-09-11
- Revision:
- 4:682d96ff6d79
- Child:
- 5:1775b4b13232
File content as of revision 4:682d96ff6d79:
#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"); } }