Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

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");
+    }
+}