Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Revision:
3:92dae9083c83
Child:
4:682d96ff6d79
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/t7utils.cpp	Tue Jun 07 12:23:28 2011 +0000
@@ -0,0 +1,580 @@
+/*******************************************************************************
+
+t7utils.cpp
+(c) 2011 by Sophie Dexter
+portions (c) Tomi Liljemark (firstname.surname@gmail.com)
+
+This C++ module provides functions for communicating simple messages to and from
+the T7 ECU
+
+********************************************************************************
+
+WARNING: Use at your own risk, sadly this software comes with no guarantees.
+This software is provided 'free' and in good faith, but the author does not
+accept liability for any damage arising from its use.
+
+*******************************************************************************/
+
+#include "t7utils.h"
+
+
+//
+// t7_initialise
+//
+// sends an initialisation message to the T7 ECU
+// but doesn't displays anything.
+//
+// inputs:    none
+// return:    bool TRUE if there was a message, FALSE if no message.
+//
+
+
+bool t7_initialise() {
+    // send a can message to the T7 requesting that it initialises CAN communication with Just4Trionic
+    char T7TxMsg[] = T7INITMSG;
+    if (!can_send_timeout (T7CMNDID, T7TxMsg, 8, T7MESSAGETIMEOUT))
+        return FALSE;
+    // wait for the T7 to reply
+    char T7RxMsg[8];
+    // if a message is not received, has the wrong id
+    if (!can_wait_timeout(T7RESPID, T7RxMsg, 8, T7MESSAGETIMEOUT))
+        return FALSE;
+    /* DEBUG info...
+        for (int i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
+        printf(" init\r\n");
+    */
+    return TRUE;
+}
+
+//
+// t7_authenticate
+//
+// sends an authentication message to the T7 ECU
+// but doesn't displays anything.
+//
+// inputs:    none
+// return:    bool TRUE if there was a message, FALSE if no message.
+//
+
+bool t7_authenticate() {
+    uint16_t seed, key;
+//    uint16_t i;
+    char T7TxAck[] = T7ACK_MSG;
+    char T7TxMsg[] = T7SEC_MSG;
+    char T7TxKey[] = T7KEY_MSG;
+    char T7RxMsg[8];
+    // Send "Request Seed" to Trionic7
+    if (!can_send_timeout (T7SEC_ID, T7TxMsg, 8, T7MESSAGETIMEOUT))
+        return FALSE;
+    // wait for the T7 to reply
+    // Read "Seed"
+    // if a message is not received id return false
+    if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT))
+        return FALSE;
+    /* DEBUG info...
+        for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
+        printf(" seed\r\n");
+    */
+    // Send Ack
+    T7TxAck[3] = T7RxMsg[0] & 0xBF;
+    if (!can_send_timeout (T7ACK_ID, T7TxAck, 8, T7MESSAGETIMEOUT))
+        return FALSE;
+    // Send "Key", try two different methods of calculating the key
+    seed = T7RxMsg[5] << 8 | T7RxMsg[6];
+    for (int method = 0; method < 2; method++ ) {
+        key = seed << 2;
+        key &= 0xFFFF;
+        key ^= ( method ? 0x4081 : 0x8142 );
+        key -= ( method ? 0x1F6F : 0x2356 );
+        key &= 0xFFFF;
+        T7TxKey[5] = ( key >> 8 ) & 0xFF;
+        T7TxKey[6] = key & 0xFF;
+        if (!can_send_timeout (T7SEC_ID, T7TxKey, 8, T7MESSAGETIMEOUT))
+            return FALSE;
+        // Wait for response
+        // if a message is not received id return false
+        if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT))
+            return FALSE;
+        /* DEBUG info...
+                for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
+                printf(" key %d 0x%02X 0x%02X\r\n", method, T7RxMsg[3], T7RxMsg[5]);
+        */
+        // Send Ack
+        T7TxAck[3] = T7RxMsg[0] & 0xBF;
+        if (!can_send_timeout (T7ACK_ID, T7TxAck, 8, T7MESSAGETIMEOUT)) {
+            /* DEBUG info...
+                        printf("Key ACK message timeout\r\n");
+            */
+            return FALSE;
+        }
+        if ( T7RxMsg[3] == 0x67 && T7RxMsg[5] == 0x34 ) {
+            /* DEBUG info...
+                        printf("Key %d Accepted\r\n", method);
+            */
+            return TRUE;
+        } else {
+            /* DEBUG info...
+                        printf("Key %d Failed\r\n", method);
+            */
+        }
+    }
+    return FALSE;
+}
+//
+// t7_dump
+//
+// dumps the T7 BIN File
+// but doesn't displays anything.
+//
+// inputs:    none
+// return:    bool TRUE if there was a message, FALSE if no message.
+//
+
+bool t7_dump() {
+    uint32_t received;
+    uint8_t byte_count, retries, i;
+    char T7_dump_jumpa[] = T7DMPJP1A;
+    char T7_dump_jumpb[] = T7DMPJP1B;
+    char T7_dump_ack[] = T7DMP_ACK;
+    char T7_dump_data[] = T7DMPDATA;
+    char T7_dump_end[] = T7DMP_END;
+    char T7RxMsg[8];
+
+    printf("Creating FLASH dump file...\r\n");
+    FILE *fp = fopen("/local/original.bin", "w");    // Open "original.bin" on the local file system for writing
+    if (!fp) {
+        perror ("The following error occured");
+        return TERM_ERR;
+    }
+
+    timer.reset();
+    timer.start();
+
+    received = 0;
+    printf("       %% complete.\r");
+    while (received < T7FLASHSIZE) {
+//        T7_dump_jumpa[7] = ((T7FLASHSIZE - received) < 0xEF) ? (T7FLASHSIZE - received) : 0xEF;
+        T7_dump_jumpb[2] = (received >> 16) & 0xFF;
+        T7_dump_jumpb[3] = (received >> 8) & 0xFF;
+        T7_dump_jumpb[4] = received & 0xFF;
+        // Send read address and length to Trionic
+        if (!can_send_timeout (T7SEC_ID, T7_dump_jumpa, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        if (!can_send_timeout (T7SEC_ID, T7_dump_jumpb, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        // Wait for a response
+        if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        /* DEBUG info...
+            for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
+            printf(" seed\r\n");
+        */
+        // Send Ack
+        T7_dump_ack[3] = T7RxMsg[0] & 0xBF;
+        if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) {
+            printf("ERROR Asking1: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        if ((T7RxMsg[3] != 0x6C) ||(T7RxMsg[4] != 0xF0)) {
+            printf("ERROR Asking2: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        // Ask T7 ECU to start sending data
+        for (retries = 0 ; retries <10 ; retries++ ) {
+            if (!can_send_timeout (T7SEC_ID, T7_dump_data, 8, T7MESSAGETIMEOUT)) {
+                printf("err t7utils line: %d\r\n", __LINE__ );
+                fclose(fp);
+                return FALSE;
+            }
+            // Read mesages from the T7 ECU
+            byte_count = 0;
+            T7RxMsg[0] = 0x00;
+            while (T7RxMsg[0] != 0x80 && T7RxMsg[0] != 0xC0) {
+                if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT))
+                    break;
+                // Need to process the received data here!
+                // Send Ack
+                T7_dump_ack[3] = T7RxMsg[0] & 0xBF;
+                if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) {
+                    printf("ERROR processing: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
+                    printf("err t7utils line: %d\r\n", __LINE__ );
+                    fclose(fp);
+                    return FALSE;
+                }
+//                /* DEBUG info...
+//                for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
+//                for (i = 2; i < 8; i++ ) printf("%c ", T7RxMsg[i] );
+//                printf(" data\r\n");
+                for (i = 2; i < 8; i++ )
+                    file_buffer[byte_count++] = (T7RxMsg[i]);
+//                */
+            }
+            // Success if these conditions met
+            if (T7RxMsg[0] == 0x80 || T7RxMsg[0] == 0xC0)
+                break;
+//            printf("retries: %d\r\n", retries);
+        }
+        if (retries > 9) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            printf("Retries: %d, Done: %5.2f %%\r\n", retries, 100*(float)received/(float)T7FLASHSIZE );
+            fclose(fp);
+            return FALSE;
+        }
+//        received += 0xEF;
+        received += 0x80;
+//        printf("Retries: %d, Done: %5.2f %%\r\n", retries, 100*(float)received/(float)T7FLASHSIZE );
+        printf("%6.2f\r", 100*(float)received/(float)T7FLASHSIZE );
+        fwrite((file_buffer + 3), 1, 0x80, fp);
+        if (ferror (fp)) {
+            fclose (fp);
+            printf ("Error writing to the FLASH BIN file.\r\n");
+            return TERM_ERR;
+        }
+    }
+    printf("\n");
+    // Send Message to T7 ECU to say that we have finished
+    if (!can_send_timeout (T7SEC_ID, T7_dump_end, 8, T7MESSAGETIMEOUT)) {
+        fclose(fp);
+        return FALSE;
+    }
+    // Wait for response
+    if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) {
+        fclose(fp);
+        return FALSE;
+    }
+// Send Ack
+    T7_dump_ack[3] = T7RxMsg[0] & 0xBF;
+    if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) {
+        printf("ERROR closing1: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if (T7RxMsg[3] != 0xC2) {
+        printf("ERROR closing2: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    timer.stop();
+    printf("SUCCESS! Getting the FLASH dump took %#.1f seconds.\r\n",timer.read());
+    fclose(fp);
+    return TRUE;
+}
+
+bool t7_erase() {
+    char T7_erase_msga[]   = { 0x40, 0xA1, 0x02, 0x31, 0x52, 0x00, 0x00, 0x00 };
+    char T7_erase_msgb[]   = { 0x40, 0xA1, 0x02, 0x31, 0x53, 0x00, 0x00, 0x00 };
+    char T7_erase_confirm[]   = { 0x40, 0xA1, 0x01, 0x3E, 0x00, 0x00, 0x00, 0x00 };
+    char T7_erase_ack[]     = { 0x40, 0xA1, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    char data[8];
+    int i;
+
+    printf("Erasing T7 ECU FLASH...\r\n");
+
+    data[3] = 0;
+    i = 0;
+    while ( data[3] != 0x71 && i < 10) {
+        // Send "Request to ERASE" to Trionic
+        if (!can_send_timeout (T7SEC_ID, T7_erase_msga, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            return FALSE;
+        }
+        if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            return FALSE;
+        }
+        T7_erase_ack[3] = data[0] & 0xBF;
+        if (!can_send_timeout (T7ACK_ID, T7_erase_ack, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            return FALSE;
+        }
+        wait_ms(100);
+        i++;
+        printf(".");
+    }
+    printf("\r\n");
+    // Check to see if erase operation lasted longer than 1 sec...
+    if (i >=10) {
+        printf("Second Message took too long'\r\n");
+        return FALSE;
+    }
+    data[3] = 0;
+    i = 0;
+    while ( data[3] != 0x71 && i < 200) {
+        // Send "Request to ERASE" to Trionic
+        if (!can_send_timeout (T7SEC_ID, T7_erase_msgb, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            return FALSE;
+        }
+        if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            return FALSE;
+        }
+        T7_erase_ack[3] = data[0] & 0xBF;
+        if (!can_send_timeout (T7ACK_ID, T7_erase_ack, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            return FALSE;
+        }
+        wait_ms(100);
+        i++;
+        printf(".");
+    }
+    printf("\r\n");
+    // Check to see if erase operation lasted longer than 20 sec...
+    if (i >=200) {
+        printf("Second Message took too long'\r\n");
+        return FALSE;
+    }
+
+    // Confirm erase was successful?
+    // (Note: no acknowledgements used for some reason)
+    if (!can_send_timeout (T7SEC_ID, T7_erase_confirm, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        return FALSE;
+    }
+    if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        return FALSE;
+    }
+    if ( data[3] != 0x7E ) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        return FALSE;
+    }
+    wait_ms(100);
+    if (!can_send_timeout (T7SEC_ID, T7_erase_confirm, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        return FALSE;
+    }
+    if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        return FALSE;
+    }
+    if ( data[3] != 0x7E ) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        return FALSE;
+    }
+    printf("SUCCESS: The FLASH has been erased.\r\n");
+    return TRUE;
+}
+
+bool t7_flash() {
+    char T7_flash_jumpa[]   = T7FLAJP1A;
+    char T7_flash_jumpb[]   = T7FLAJP1B;
+    char T7_flash_end[]     = T7FLA_END;
+    char T7_flash_exit[]    = T7FLAEXIT;
+    char T7_flash_ack[]     = T7FLA_ACK;
+    char data[8];
+    int i, k;
+
+    // fopen modified.hex here?
+    // need lots of fcloses though
+    printf("Checking the FLASH BIN file...\r\n");
+    FILE *fp = fopen("/local/modified.hex", "r");    // Open "modified.hex" on the local file system for reading
+    if (!fp) {
+        printf("Error: I could not find the BIN file MODIFIED.HEX\r\n");;
+        return TERM_ERR;
+    }
+    // obtain file size - it should match the size of the FLASH chips:
+    fseek (fp , 0 , SEEK_END);
+    uint32_t file_size = ftell (fp);
+    rewind (fp);
+
+    // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU
+    uint8_t stack_byte = 0;
+    uint32_t stack_long = 0;
+    if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
+    stack_long |= (stack_byte << 24);
+    if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
+    stack_long |= (stack_byte << 16);
+    if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
+    stack_long |= (stack_byte << 8);
+    if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
+    stack_long |= stack_byte;
+    rewind (fp);
+
+    if (file_size != T7FLASHSIZE || stack_long != T7POINTER) {
+        fclose(fp);
+        printf("The BIN file does not appear to be for a T7 ECU :-(\r\n");
+        printf("BIN file size: %#010x, FLASH chip size: %#010x, Pointer: %#010x.\r\n", file_size, T7FLASHSIZE, stack_long);
+        return TERM_ERR;
+    }
+
+    timer.reset();
+    timer.start();
+
+    // Send "Request Download - tool to module" to Trionic
+    if (!can_send_timeout (T7SEC_ID, T7_flash_jumpa, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if (!can_send_timeout (T7SEC_ID, T7_flash_jumpb, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    T7_flash_ack[3] = data[0] & 0xBF;
+    if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if ( data[3] != 0x74 ) {
+        printf("Cannot Update FLASH, message refused.\r\n");
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+
+    uint32_t address = 0;
+
+    printf("       %% complete.\r");
+    while (address < T7FLASHSIZE) {
+
+        data[0] = 0x4A; // 0x40 send, | 0x0A (10) messages to follow
+//        data[0] = 0x42; // 0x40 send, | 0x02 (2) messages to follow
+//        data[0] = 0x40; // 0x40 send, | 0x00 (0) messages to follow
+        data[1] = 0xA1;
+        data[2] = 0x41; // length+1 (64 Bytes)
+//        data[2] = 0x11; // length+1 (16 Bytes)
+//        data[2] = 0x05; // length+1 (4 Bytes)
+        data[3] = 0x36; // Data Transfer
+        for ( k = 4; k < 8; k++ )
+            //data[k] = *(bin + bin_count++);
+            if (!fread(&data[k],1,1,fp)) {
+                fclose(fp);
+                printf("Error reading the BIN file MODIFIED.HEX");
+                return FALSE;
+            }
+//      /* DEBUG info...
+//        for (k = 0; k < 8; k++ ) printf("0x%02X ", data[k] );
+//        for (k = 2; k < 8; k++ ) printf("%c ", data[k] );
+//        printf(" data\r\n");
+
+        if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+//*
+        for (i = 9; i>=0; i--) {
+//        for (i = 1; i>=0; i--) {
+            data[0] = i;
+            // data[1] = 0xA1;
+            for ( k = 2; k < 8; k++ )
+                //data[k] = *(bin + bin_count++);
+                if (!fread(&data[k],1,1,fp)) {
+                    fclose(fp);
+                    printf("Error reading the BIN file MODIFIED.HEX");
+                    return FALSE;
+                }
+//            /* DEBUG info...
+//            for (k = 0; k < 8; k++ ) printf("0x%02X ", data[k] );
+//            for (k = 2; k < 8; k++ ) printf("%c ", data[k] );
+//            printf(" data\r\n");
+
+//            printf("%6.2f\r", 100*(float)address/(float)T7FLASHSIZE );
+            wait_ms(1);
+            if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
+                printf("err t7utils line: %d\r\n", __LINE__ );
+                fclose(fp);
+                return FALSE;
+            }
+        }
+//*/
+        address += 0x40;
+//        address += 0x10;
+//        address += 0x04;
+        if (!can_wait_timeout(T7SEC_RX, data, 8, T7LONGERTIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        // Send acknowledgement
+        T7_flash_ack[3] = data[0] & 0xBF;
+        if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        if ( data[3] != 0x76 ) {
+            printf("err t7utils line: %d\r\n", __LINE__ );
+            fclose(fp);
+            return FALSE;
+        }
+        if (!(address % 0x80))
+            printf("%6.2f\r", 100*(float)address/(float)T7FLASHSIZE );
+    }
+    printf("\n");
+/*
+    // Send "Request Data Transfer Exit" to Trionic
+    if (!can_send_timeout (T7SEC_ID, T7_flash_end, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    T7_flash_ack[3] = data[0] & 0xBF;
+    if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if ( data[3] != 0x77 ) {
+        printf("Cannot Update FLASH, message refused.\r\n");
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    // Send "Request Data Transfer Exit" to Trionic
+    if (!can_send_timeout (T7SEC_ID, T7_flash_exit, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    T7_flash_ack[3] = data[0] & 0xBF;
+    if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+    if ( data[3] != 0x71 ) {
+        printf("Cannot Update FLASH, message refused.\r\n");
+        printf("err t7utils line: %d\r\n", __LINE__ );
+        fclose(fp);
+        return FALSE;
+    }
+*/
+    timer.stop();
+    printf("SUCCESS! Programming the FLASH took %#.1f seconds.\r\n",timer.read());
+    fclose(fp);
+    return TRUE;
+}
\ No newline at end of file