Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
Just4pLeisure
Date:
Sat Apr 23 18:31:40 2016 +0000
Parent:
5:1775b4b13232
Commit message:
Version 1.6 Faster T7 P-BUS FLASHing algorithm, longer T8 erase timeout fixed BDM register display function

Changed in this revision

bdm.cpp Show annotated file Show diff for this revision Revisions of this file
bdmtrionic.cpp Show annotated file Show diff for this revision Revisions of this file
common.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
t7can.cpp Show annotated file Show diff for this revision Revisions of this file
t7utils.cpp Show annotated file Show diff for this revision Revisions of this file
t7utils.h Show annotated file Show diff for this revision Revisions of this file
t8utils.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 1775b4b13232 -r 2fbcbebed28c bdm.cpp
--- a/bdm.cpp	Sat Apr 25 17:07:08 2015 +0000
+++ b/bdm.cpp	Sat Apr 23 18:31:40 2016 +0000
@@ -423,20 +423,22 @@
             // registers
         case CMDGROUP_REGISTER:
             // get register code
-            if (cmd_length == 2 && (cmd != CMD_DISPLAYREGS)) {
-                // broken parametre
-                return TERM_ERR;
-            } else {
-                if (cmd_length < 4 || !ascii2int(&cmd_addr, cmd_buffer + 3, 1)) {
+            if (cmd_length == 2) {
+                if (cmd != CMD_DISPLAYREGS) {
                     // broken parametre
+                    printf("err %s line: %d, cmd_length %d\r\n", __FILE__, __LINE__, cmd_length);
                     return TERM_ERR;
                 }
-                // get optional value
-                if (cmd_length > 4 &&
-                        !ascii2int(&cmd_value, cmd_buffer + 4, 8)) {
-                    // broken parametre
-                    return TERM_ERR;
-                }
+            } else if (cmd_length < 4 || !ascii2int(&cmd_addr, cmd_buffer + 3, 1)) {
+                // broken parametre
+                printf("err %s line: %d, cmd_length %d\r\n", __FILE__, __LINE__, cmd_length);
+                return TERM_ERR;
+            }
+            // get optional value
+            if (cmd_length > 4 && !ascii2int(&cmd_value, cmd_buffer + 4, 8)) {
+                // broken parametre
+                printf("err %s line: %d, cmd_length %d\r\n", __FILE__, __LINE__, cmd_length);
+                return TERM_ERR;
             }
 
             switch (cmd) {
@@ -444,6 +446,7 @@
                 case CMD_READSYSREG:
                     if (cmd_length != 4 ||
                             sysreg_read(&cmd_result, (uint8_t)cmd_addr) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("%08X", cmd_result);
@@ -460,6 +463,7 @@
                 case CMD_READADREG:
                     if (cmd_length != 4 ||
                             adreg_read(&cmd_result, (uint8_t)cmd_addr) != TERM_OK) {
+                        printf("err %s line: %d, cmd_length %d\r\n", __FILE__, __LINE__, cmd_length);
                         return TERM_ERR;
                     }
                     printf("%08X", cmd_result);
@@ -474,9 +478,11 @@
 
                     // Display all registers
                 case CMD_DISPLAYREGS:
+                    printf(" Register Display\r\n");
                     printf(" D0-7");
                     for (uint8_t i = 0; i < 8; i++) {
                         if (adreg_read(&cmd_result, i) != TERM_OK) {
+                            printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                             return TERM_ERR;
                         }
                         printf(" %08X", cmd_result);
@@ -486,6 +492,7 @@
                     printf(" A0-7");
                     for (uint8_t i = 8; i < 16; i++) {
                         if (adreg_read(&cmd_result, i) != TERM_OK) {
+                            printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                             return TERM_ERR;
                         }
                         printf(" %08X", cmd_result);
@@ -493,31 +500,39 @@
                     printf("\r\n");
 //
                     if (sysreg_read(&cmd_result, 0x0) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("  RPC %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0xC) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("     USP %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0xE) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("     SFC %08X      SR 10S--210---XNZVC\r\n", cmd_result);
 //
                     if (sysreg_read(&cmd_result, 0x1) != TERM_OK) {
+
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("  CPC %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0xD) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("     SSP %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0xF) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("     DFC %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0xB) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("    %04X ", cmd_result);
@@ -527,14 +542,17 @@
                     printf("\r\n");
 //
                     if (sysreg_read(&cmd_result, 0xA)!= TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("  VBR %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0x8)!= TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("   ATEMP %08X", cmd_result);
                     if (sysreg_read(&cmd_result, 0x9) != TERM_OK) {
+                        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
                         return TERM_ERR;
                     }
                     printf("     FAR %08X\r\n", cmd_result);
@@ -580,7 +598,7 @@
             bdm_show_help();
     }
 
-    // unknown command
+// unknown command
     return TERM_ERR;
 }
 
@@ -589,9 +607,10 @@
     printf("Just4Trionic BDM Command Menu\r\n");
     printf("=============================\r\n");
     printf("TD - and DUMP T5 FLASH BIN file\r\n");
-    printf("TF - FLASH the update file to the T5 (and write SRAM)\r\n");
-    printf("Tr - Read SRAM adaption (not done).\r\n");
-    printf("Tw - Write SRAM adaptation (not done).\r\n");
+    printf("TF - FLASH the update file to the T5\r\n");
+//    printf("TF - FLASH the update file to the T5 (and write SRAM)\r\n");
+//    printf("Tr - Read SRAM adaption (not done).\r\n");
+//    printf("Tw - Write SRAM adaptation (not done).\r\n");
     printf("\r\n");
     printf("'ESC' - Return to Just4Trionic Main Menu\r\n");
     printf("\r\n");
@@ -604,9 +623,10 @@
     printf("Just4Trionic BDM Command Menu\r\n");
     printf("=============================\r\n");
     printf("TD - and DUMP T5 FLASH BIN file\r\n");
-    printf("TF - FLASH the update file to the T5 (and write SRAM)\r\n");
-    printf("Tr - Read SRAM adaption (not done).\r\n");
-    printf("Tw - Write SRAM adaptation (not done).\r\n");
+    printf("TF - FLASH the update file to the T5\r\n");
+//    printf("TF - FLASH the update file to the T5 (and write SRAM)\r\n");
+//    printf("Tr - Read SRAM adaption (not done).\r\n");
+//    printf("Tw - Write SRAM adaptation (not done).\r\n");
     printf("\r\n");
     printf("Adapter Commands - a\r\n");
     printf("====================\r\n");
diff -r 1775b4b13232 -r 2fbcbebed28c bdmtrionic.cpp
--- a/bdmtrionic.cpp	Sat Apr 25 17:07:08 2015 +0000
+++ b/bdmtrionic.cpp	Sat Apr 23 18:31:40 2016 +0000
@@ -1180,7 +1180,7 @@
 //            if (sysreg_write(0x0, &driverAddress) != TERM_OK) return TERM_ERR;
 //            break;
             do {
-                if (!bdmRunDriver(0x0, 20000)) {
+                if (!bdmRunDriver(0x0, 200000)) {
                     printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n");
                     return TERM_ERR;
                 }
diff -r 1775b4b13232 -r 2fbcbebed28c common.h
--- a/common.h	Sat Apr 25 17:07:08 2015 +0000
+++ b/common.h	Sat Apr 23 18:31:40 2016 +0000
@@ -37,7 +37,7 @@
 
 // constants
 #define FW_VERSION_MAJOR    0x1     ///< firmware version
-#define FW_VERSION_MINOR    0x2        
+#define FW_VERSION_MINOR    0x6        
 
 #define CR 0x0D
 #define NL 0x0A
diff -r 1775b4b13232 -r 2fbcbebed28c main.cpp
--- a/main.cpp	Sat Apr 25 17:07:08 2015 +0000
+++ b/main.cpp	Sat Apr 23 18:31:40 2016 +0000
@@ -28,6 +28,25 @@
 
 ********************************************************************************
 
+Version 1.6 (04/2016)
+
+Fixed since Version 1.5:
+    BDM
+        Improvements to CPU register content display
+        T8 erase timeout period to 200 seconds (was incorrectly only 20 seconds)
+
+Added since Version 1.5:
+    T7 CAN functions:
+        Separate FLASHing algorithms for I and P-BUS connections
+        Completely safe, but slow, I-BUS algorithm
+        Pseudo 'recovery' FLASHing function can be used to retry a failed
+        FLASH with safe, slow algorithm
+        
+Changes since Version 1.5:
+    Additional debug messages
+    T7 CAN functions:
+        Code refactoring to make file handling simpler
+
 Version 1.5 (04/2015)
 
 Added since Version 1.4
@@ -183,14 +202,6 @@
     while (pc.readable())
         rx_char = pc.getc();
 
-#ifdef DEBUG
-    printf("*************************\r\n");
-    printf("** RUNNING DEBUG BUILD **\r\n");
-    printf("*************************\r\n");
-#else
-    printf("Running... this is a release build.\r\n");
-#endif
-
     show_just4trionic_help();
 
     // main loop
@@ -279,13 +290,21 @@
 
 void show_just4trionic_help()
 {
-    printf("Just4Trionic Command Menu\r\n");
+#ifdef DEBUG
+    printf("*************************\r\n");
+    printf("** D E B U G B U I L D **\r\n");
+    printf("*************************\r\n");
+#endif
+    printf("=========================\r\n");
+    printf("Just4Trionic Release %d.%d\r\n", FW_VERSION_MAJOR, FW_VERSION_MINOR);
     printf("=========================\r\n");
-    printf("b/B - Start BDM interface\r\n");
-    printf("o/O - Open Lawicel CAN232 type interface\r\n");
-    printf("5   - Start Trionic5 ECU CAN interface\r\n");
-    printf("7   - Start Trionic7 ECU CAN interface\r\n");
-    printf("8   - Start Trionic8 ECU CAN interface\r\n");
+    printf("Modes Menu\r\n");
+    printf("=========================\r\n");
+    printf("b/B - Enter BDM mode\r\n");
+    printf("o/O - Enter Lawicel CAN mode\r\n");
+    printf("5   - Enter Trionic5 CAN mode\r\n");
+    printf("7   - Enter Trionic7 CAN mode\r\n");
+    printf("8   - Enter Trionic8 CAN mode\r\n");
     printf("\r\n");
     printf("h/H - show this help menu\r\n");
     printf("\r\n");
diff -r 1775b4b13232 -r 2fbcbebed28c t7can.cpp
--- a/t7can.cpp	Sat Apr 25 17:07:08 2015 +0000
+++ b/t7can.cpp	Sat Apr 23 18:31:40 2016 +0000
@@ -42,18 +42,26 @@
 void t7_can_show_help();
 void t7_can_show_full_help();
 
-void t7_can() {
+// private variables
+bool ibus = false;
+bool pbus = false;
+
+void t7_can()
+{
     // Start the CAN bus system
     // Note that at the moment this is only for T7 ECUs at 500 kbits
     t7_can_show_help();
 
     char data[8];
+    ibus = false;
+    pbus = false;
     printf("Trying to listen to CAN I-Bus (47619 Bit/s)...\r\n");
     can_configure(2, 47619, 1);
     if (can_wait_timeout(T7ANYMSG, data, 8, T7MESSAGETIMEOUT)) {
         printf("Connected to Saab I-Bus\r\n");
         printf("Switching to I-Bus active mode\r\n");
         can_configure(2, 47619, 0);
+        ibus = true;
     } else {
         printf("I did not receive any I-Bus messages\r\n");
         printf("Trying to listen to  CAN P-Bus (500 kBit/s)...\r\n");
@@ -62,12 +70,14 @@
             printf("Connected to Saab P-Bus\r\n");
             printf("Switching to P-Bus active mode\r\n");
             can_configure(2, 500000, 0);
+            pbus = true;
         } else {
             printf("I did not receive any P-Bus messages\r\n");
             printf("Switching to P-Bus active mode\r\n");
             can_configure(2, 500000, 0);
             if (can_wait_timeout(T7ANYMSG, data, 8, T7CONNECTTIMEOUT)) {
                 printf("Connected to Saab P-Bus\r\n");
+                pbus = true;
                 //can_active();
             } else {
                 printf("FAILED to connect!\r\n");
@@ -153,108 +163,156 @@
 
     @return                    command flag (success / failure)
 */
-uint8_t execute_t7_cmd() {
+uint8_t execute_t7_cmd()
+{
 
-    char data[8];
 //    uint8_t cmd_length = strlen(cmd_buffer);
     // command groups
     switch (*cmd_buffer) {
 //            CHECK_ARGLENGTH(0);
-            // Get the Symbol Table
+        // Initialise a T7 CAN session
         case 'i' :
             if (t7_initialise()) {
-                printf("Trionic 7 Connection OK\r\n");
+                printf("SUCCESS! Trionic 7 CAN Connection OK.\r\n");
                 return TERM_OK;
             } else {
-                printf("Trionic 7 Connection Failed\r\n");
+                printf("FAILURE! No CAN connection to Trionic 7.\\r\n");
                 return TERM_ERR;
             }
-//            return t7_initialise()
-//                   ? TERM_OK : TERM_ERR;
+        // Get security clearance for T7 CAN session
         case 'a' :
-        case 'A' :
             if (t7_authenticate()) {
-                printf("Security Key Accepted\r\n");
+                printf("SUCCESS! Security Key Accepted.\r\n");
                 return TERM_OK;
             } else {
-                printf("Security Key Failed\r\n");
+                printf("FAILURE! Unable to obtain a Security Key.\\r\n");
                 return TERM_ERR;
             }
-//            return t7_authenticate()
-//                   ? TERM_OK : TERM_ERR;
-
-// Erase the FLASH chips
+        // Erase the FLASH chips
         case 'e':
-        case 'E':
             return t7_erase()
                    ? TERM_OK : TERM_ERR;
-// DUMP the T5 ECU BIN file stored in the FLASH chips
+        // DUMP the T5 ECU BIN file stored in the FLASH chips
         case 'D':
             if (!t7_authenticate()) {
                 if (!t7_initialise()) {
-                    printf("Trionic 7 Connection Failed\r\n");
+                    printf("FAILURE! No CAN connection to Trionic 7.\r\n");
                     return TERM_ERR;
                 }
                 if (!t7_authenticate()) {
-                    printf("Security Key Failed\r\n");
+                    printf("FAILURE! Unable to obtain a Security Key.\r\n");
                     return TERM_ERR;
                 }
             }
         case 'd':
-            return t7_dump()
+            return t7_dump(pbus)
                    ? TERM_OK : TERM_ERR;
 // Send a FLASH update file to the T5 ECU
-        case 'F':
+        case 'F': {
+            FILE *fp = t7_file_open("/local/modified.bin");    // Open "modified.bin" on the local file system
+            if (!fp) {
+                printf("FAILURE! Unable to find the BIN file \"MODIFIED.BIN\"\r\n");
+                return TERM_ERR;
+            }
             if (!t7_authenticate()) {
                 if (!t7_initialise()) {
-                    printf("Trionic 7 Connection Failed\r\n");
+                    printf("FAILURE! No CAN connection to Trionic 7.\r\n");
+                    fclose(fp);
                     return TERM_ERR;
                 }
                 if (!t7_authenticate()) {
-                    printf("Security Key Failed\r\n");
+                    printf("FAILURE! Unable to obtain a Security Key.\r\n");
+                    fclose(fp);
                     return TERM_ERR;
                 }
             }
             if (!t7_erase()) {
-                printf("Could not Erase FLASH!\r\n");
+                printf("FAILURE: Unable to Erase FLASH!\r\n");
+                fclose(fp);
+                return TERM_ERR;
+            }
+            bool result = t7_flash(fp, pbus);
+            fclose(fp);
+            return result ? TERM_OK : TERM_ERR;
+        }
+        case 'f': {
+            FILE *fp = t7_file_open("/local/modified.bin");    // Open "modified.bin" on the local file system
+            if (!fp) {
+                printf("FAILURE! Unable to find the BIN file \"MODIFIED.BIN\"\r\n");
+                return TERM_ERR;
+            }
+            bool result = t7_flash(fp, pbus);
+            fclose(fp);
+            return result ? TERM_OK : TERM_ERR;
+        }
+// Recovery FLASHes the entire BIN file and using 'safe' but slow 4 byte at a time transfers
+        case 'R': {
+            FILE *fp = t7_file_open("/local/modified.bin");    // Open "modified.bin" on the local file system
+            if (!fp) {
+                printf("FAILURE! Unable to find the BIN file \"MODIFIED.BIN\"\r\n");
                 return TERM_ERR;
             }
-        case 'f':
-            return t7_flash()
-                   ? TERM_OK : TERM_ERR;
+            if (!t7_authenticate()) {
+                if (!t7_initialise()) {
+                    printf("FAILURE! No CAN connection to Trionic 7.\r\n");
+                    fclose(fp);
+                    return TERM_ERR;
+                }
+                if (!t7_authenticate()) {
+                    printf("FAILURE! Unable to obtain a Security Key.\r\n");
+                    fclose(fp);
+                    return TERM_ERR;
+                }
+            }
+            if (!t7_erase()) {
+                printf("FAILURE: Unable to Erase FLASH!\r\n");
+                fclose(fp);
+                return TERM_ERR;
+            }
+            bool result = t7_recover(fp);
+            fclose(fp);
+            return result ? TERM_OK : TERM_ERR;
+        }
 // Try to connect to CAN I-BUS
-        case 'I' :
+        case 'I' : {
+            char data[8];
             printf("Trying to open CAN I-Bus (47619 Bit/s)...\r\n");
+            ibus = true;
+            pbus = false;
             can_close();
             //can_monitor();
             can_set_speed(47619);
             can_open();
             if (can_wait_timeout(T7ANYMSG, data, 8, T7CONNECTTIMEOUT)) {
-                printf("Connected to Saab I-Bus\r\n");
+                printf("SUCCESS! Connected to Saab I-Bus.\r\n");
                 //can_active();
                 return TERM_OK;
             } else {
                 printf("I did not receive any I-Bus messages\r\n");
-                printf("FAILED to connect!\r\n");
+                printf("FAILURE! Unable to connect Saab I-Bus.\r\n");
                 return TERM_ERR;
             }
+        }
 // Try to connect to CAN P-BUS
-        case 'P' :
+        case 'P' : {
+            char data[8];
             printf("Trying to open CAN P-Bus (500 kBit/s)...\r\n");
+            ibus = false;
+            pbus = true;
             can_close();
             //can_monitor();
             can_set_speed(500000);
             can_open();
             if (can_wait_timeout(T7ANYMSG, data, 8, T7CONNECTTIMEOUT)) {
-                printf("Connected to Saab P-Bus\r\n");
+                printf("SUCCESS! Connected to Saab P-Bus.\r\n");
                 //can_active();
                 return TERM_OK;
             } else {
                 printf("I did not receive any P-Bus messages\r\n");
-                printf("FAILED to connect!\r\n");
+                printf("FAILURE! Unable to connect Saab P-Bus.\r\n");
                 return TERM_ERR;
             }
-
+        }
 // Print help
         case 'h':
             t7_can_show_help();
@@ -278,11 +336,13 @@
 // inputs:    none
 // return:    none
 //
-void t7_can_show_help() {
+void t7_can_show_help()
+{
     printf("Trionic 7 Command Menu\r\n");
     printf("======================\r\n");
     printf("D - DUMP the T7 ECU FLASH to a file 'ORIGINAL.BIN'\r\n");
     printf("F - FLASH the update file 'MODIFIED.BIN' to the T7\r\n");
+    printf("R - Recovery FLASH T7 with update file 'MODIFIED.BIN'\r\n");
     printf("\r\n");
     printf("I - Try to open CAN I-Bus (47619 Bit/s)\r\n");
     printf("P - Try to open CAN P-Bus (500 kBit/s)\r\n");
@@ -301,11 +361,13 @@
 // inputs:    none
 // return:    none
 //
-void t7_can_show_full_help() {
+void t7_can_show_full_help()
+{
     printf("Trionic 7 Command Menu\r\n");
     printf("======================\r\n");
     printf("D - DUMP the T7 ECU FLASH to a file 'ORIGINAL.BIN'\r\n");
     printf("F - FLASH the update file 'MODIFIED.BIN' to the T7\r\n");
+    printf("R - Recovery FLASH T7 with update file 'MODIFIED.BIN'\r\n");
     printf("\r\n");
     printf("I - Try to open CAN I-Bus (47619 Bit/s)\r\n");
     printf("P - Try to open CAN P-Bus (500 kBit/s)\r\n");
diff -r 1775b4b13232 -r 2fbcbebed28c t7utils.cpp
--- a/t7utils.cpp	Sat Apr 25 17:07:08 2015 +0000
+++ b/t7utils.cpp	Sat Apr 23 18:31:40 2016 +0000
@@ -29,7 +29,8 @@
 //
 
 
-bool t7_initialise() {
+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))
@@ -56,7 +57,8 @@
 // return:    bool TRUE if there was a message, FALSE if no message.
 //
 
-bool t7_authenticate() {
+bool t7_authenticate()
+{
     uint16_t seed, key;
 //    uint16_t i;
     char T7TxAck[] = T7ACK_MSG;
@@ -130,7 +132,8 @@
 // return:    bool TRUE if there was a message, FALSE if no message.
 //
 
-bool t7_dump() {
+bool t7_dump(bool blockmode)
+{
     uint32_t received;
     uint8_t byte_count, retries, i;
     char T7_dump_jumpa[] = T7DMPJP1A;
@@ -275,10 +278,11 @@
     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 };
+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;
@@ -290,16 +294,16 @@
     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__ );
+            printf("err %s line: %d\r\n", __FILE__, __LINE__ );
             return FALSE;
         }
         if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-            printf("err t7utils line: %d\r\n", __LINE__ );
+            printf("err %s line: %d\r\n", __FILE__, __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__ );
+            printf("err %s line: %d\r\n", __FILE__, __LINE__ );
             return FALSE;
         }
         wait_ms(100);
@@ -317,16 +321,16 @@
     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__ );
+            printf("err %s line: %d\r\n", __FILE__, __LINE__ );
             return FALSE;
         }
         if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-            printf("err t7utils line: %d\r\n", __LINE__ );
+            printf("err %s line: %d\r\n", __FILE__, __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__ );
+            printf("err %s line: %d\r\n", __FILE__, __LINE__ );
             return FALSE;
         }
         wait_ms(100);
@@ -343,487 +347,341 @@
     // 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__ );
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if ( data[3] != 0x7E ) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
+        printf("err %s line: %d\r\n", __FILE__, __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__ );
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if ( data[3] != 0x7E ) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
+        printf("FAILURE: Unable to erase the FLASH .\r\n");
         return FALSE;
     }
     printf("SUCCESS: The FLASH has been erased.\r\n");
     return TRUE;
 }
 
-bool t7_flash_raw() {
-    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.bin here?
-    // need lots of fcloses though
+/// Open and check the bin file to make sure that it is a valid T7 BIN file
+///
+/// params  full filename including path of the T7 BIN file
+///
+/// returns a pointer to the T7 BIN file
+///         or a null pointer if it is invalid in some way
+
+FILE * t7_file_open(const char* fname)
+{
     printf("Checking the FLASH BIN file...\r\n");
-    FILE *fp = fopen("/local/modified.bin", "r");    // Open "modified.bin" on the local file system for reading
+    FILE *fp = fopen(fname, "r");    // Open "modified.bin" on the local file system for reading
     if (!fp) {
         printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");;
-        return TERM_ERR;
+        return NULL;
     }
     // 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);
+    if (file_size != T7FLASHSIZE) {
+        fclose(fp);
+        printf("The BIN file does not appear to be for a T7 ECU :-(\r\n");
+        printf("T7's FLASH chip size is: %#010x bytes.\r\n", T7FLASHSIZE);
+        printf("The BIN's file size is: %#010x bytes.\r\n", file_size);
+        return NULL;
+    }
 
     // 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;
+    for (uint32_t i=0; i<4; i++) {
+        if (!fread(&stack_byte,1,1,fp)) {
+            printf("Error reading the BIN file MODIFIED.BIN\r\n");
+            return NULL;
+        }
+        stack_long <<= 8;
+        stack_long |= stack_byte;
+    }
     rewind (fp);
-
-    if (file_size != T7FLASHSIZE || stack_long != T7POINTER) {
+    if (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;
+        printf("A T7 BIN file should start with: %#010x.\r\n", T7POINTER);
+        printf("This file starts with : %#010x.\r\n", stack_long);
+        return NULL;
+    }
+    printf("The BIN file appears to OK :-)\r\n");
+    return fp;
+}
+
+
+bool t7_flash_segment(FILE *fp, uint32_t address, uint32_t size, bool blockmode)
+{
+    char T7_flash_start[]   = T7FLASTRT;
+    char T7_flash_size[]    = T7FLASIZE;
+    char T7_flash_ack[]     = T7FLA_ACK;
+    char data[8];
+
+    int32_t i, k;
+
+    uint32_t current_address = address;
+    uint32_t segment_end = address + size;
+
+    if ((current_address > T7FLASHSIZE) || (segment_end > T7FLASHSIZE)) {
+        printf("Attempting to FLASH outside of FLASH region\r\n");
+        printf("Start Address: %#010x, End Address: %#010x.\r\n", current_address, segment_end);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
+        return FALSE;
     }
 
-    timer.reset();
-    timer.start();
+    // blocksize can be any size between 1 and 250 (0x01 - 0xFA)
+    // Better performance is realised with a bigger blocksize
+    //
+    // The following convenient sizes to use for testing
+    //     0x04, 0x10 and 0x40
+    // A value of 0x70 is useful when programming the BIN region
+    //uint32_t blocksize = (blockmode == true) ? 0x70 : 0x04;
+    uint32_t blocksize = (blockmode == true) ? 0xFA : 0x04;
+    // Sanity check 
+    if (blocksize < 0x01) blocksize = 0x01;
+    if (blocksize > 0xFA) blocksize = 0xFA;
+    uint32_t blockquantity, blockremainder, blockfirst, blockduring;
 
-    // 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);
+    if (fseek (fp , address , SEEK_SET) != 0x0) {
+        printf("Cannot move to file position %#010x.\r\n", current_address);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
-    if (!can_send_timeout (T7SEC_ID, T7_flash_jumpb, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+    for(i=0; i<3; i++) {
+        T7_flash_start[6-i] = (address >> (8*i)) & 0xff;
+        T7_flash_size[4-i] = (size >> (8*i)) & 0xff;
+    }
+
+    // Send "Request Download - tool to module" to Trionic for the BIN file code and 'cal' data
+    if (!can_send_timeout (T7SEC_ID, T7_flash_start, 8, T7MESSAGETIMEOUT)) {
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
+        return FALSE;
+    }
+    if (!can_send_timeout (T7SEC_ID, T7_flash_size, 8, T7MESSAGETIMEOUT)) {
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         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);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if ( data[3] != 0x74 ) {
         printf("Cannot Update FLASH, message refused.\r\n");
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
 
-    uint32_t address = 0;
-
+// FLASH main Binary image up to address + size
     printf("  0.00 %% complete.\r");
-    while (address < T7FLASHSIZE) {
+    while (current_address < segment_end) {
+        if ((segment_end - current_address) < blocksize) {
+            blocksize = (segment_end - current_address);
+            wait_ms(T7MESSAGETIMEOUT);
+        }
+        if (blocksize > 4) {
+            blockfirst = 4;
+            blockquantity = (blocksize - blockfirst) / 6;
+            blockremainder = (blocksize - blockfirst) % 6;
+            if (blockremainder != 0) {
+                blockquantity++;
+            }
+        } else {
+            blockfirst = blocksize;
+            blockquantity = 0;
+            blockremainder = 0;
+        }
 
-//        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[0] = 0x40 + blockquantity; // e.g 0x40 send, | 0x0A (10) 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[2] = blocksize + 1; // length+1 (64 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.BIN\r\n");
-                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);
+        if (!fread((data+4),1,blockfirst,fp)) {
+            printf("\nError reading the BIN file MODIFIED.BIN\r\n");
             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.BIN\r\n");
-                            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);
-        //            wait_ms(10);   // 31/3/12 this longer wait might be needed for i-bus connections...
-                    if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
-                        printf("err t7utils line: %d\r\n", __LINE__ );
-                        fclose(fp);
-                        return FALSE;
-                    }
+#ifdef DEBUG
+// 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");
+#endif
+        if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
+            printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
+            return FALSE;
+        }
+        if (blocksize > 4) {
+            for (i = (blockquantity-1); i>=0; i--) {
+                data[0] = i;
+                if ((i == 0) && (blockremainder != 0)) {
+                    blockduring = blockremainder;
+                } else {
+                    blockduring = 6;
                 }
-        */
-//        address += 0x40;
-//        address += 0x10;
-        address += 0x04;
+                if (!fread((data+2),1,blockduring,fp)) {
+                    printf("\nError reading the BIN file MODIFIED.BIN\r\n");
+                    return FALSE;
+                }
+#ifdef DEBUG
+//  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)current_address/(float)T7FLASHSIZE );
+#endif
+                wait_us(300);
+//                wait_ms(10);   // 31/3/12 this longer wait might be needed for i-bus connections...
+                if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
+                    printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
+                    return FALSE;
+                }
+            }
+        }
         if (!can_wait_timeout(T7SEC_RX, data, 8, T7LONGERTIMEOUT)) {
-            printf("err t7utils line: %d\r\n", __LINE__ );
-            fclose(fp);
+            printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
             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);
+            printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
             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);
+            printf ("\n");
+//#ifdef DEBUG
+//  DEBUG info...
+            for (k = 0; k < 8; k++ ) printf("%#04x ", data[k] );
+            for (k = 2; k < 8; k++ ) printf("%c ", data[k] );
+            printf(" data\r\n");
+//#endif
+            printf("Cannot Program Address %#010x.\r\n", current_address);
+            printf("Block Size %#04x, First %#04x, Quantity %#04x, Remainder %#04x\r\n", blocksize, blockfirst, blockquantity, blockremainder);
+            printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
             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);
+        current_address += blocksize;
+//        if (!(current_address % 0x80))
+            printf("%6.2f\r", 100*(float)current_address/(float)T7FLASHSIZE );
+    }
+    if (blockmode == true) wait_ms(T7MESSAGETIMEOUT);
     return TRUE;
 }
 
+bool t7_flash(FILE *fp, bool blockmode)
+{
+    timer.reset();
+    timer.start();
+    printf("T7 program and caldata\r\n");
+    if (t7_flash_segment(fp, 0x000000, 0x070000, blockmode)) {              // T7 program and caldata
+        printf("\nAdaptation data 1\r\n");
+        if (t7_flash_segment(fp, 0x070000, 0x002000, blockmode)) {          // Adaptation data 1
+            printf("\nAdaptation data 2\r\n");
+            if (t7_flash_segment(fp, 0x07C000, 0x00280, blockmode)) {       // Adaptation data 2
+                printf("\nT7Suite watermark\r\n");
+                if (t7_flash_segment(fp, 0x07FD00, 0x000020, blockmode)) {      // T7Suite watermark
+                    printf("\nT7 Header\r\n");
+                    if (t7_flash_segment(fp, 0x07FF00, 0x000100, blockmode)) {  // T7 Header
+                        timer.stop();
+                        printf("100.00\r\n");
+                        printf("SUCCESS! Programming the FLASH took %#.1f seconds.\r\n",timer.read());
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    timer.stop();
+    printf("\nFAILURE! Unable to program FLASH after %#.1f seconds.\r\n",timer.read());
+    return false;
+}
 
-bool t7_flash() {
-    char T7_flash_jumpa[]   = T7FLABINA;
-    char T7_flash_jumpb[]   = T7FLABINB;
-    char T7_flash_jumpc[]   = T7FLAHDRA;
-    char T7_flash_jumpd[]   = T7FLAHDRB;
-    char T7_flash_end[]     = T7FLA_END;
+bool t7_recover(FILE *fp)
+{
+    timer.reset();
+    timer.start();
+    if (t7_flash_segment(fp, 0x000000, 0x080000, false)) {              // Entire T7 BIN File
+        timer.stop();
+        printf("100.00\r\n");
+        printf("SUCCESS! Programming the FLASH took %#.1f seconds.\r\n",timer.read());
+        return true;
+    }
+    timer.stop();
+    printf("\nFAILURE! Unable to program FLASH after %#.1f seconds.\r\n",timer.read());
+    return false;
+}
+
+
+/// Reset and restart a T7 ECU after a FLASH operation
+///
+/// NOTE: DOESN't WORK !!!
+///
+bool t7_reset()
+{
     char T7_flash_exit[]    = T7FLAEXIT;
     char T7_flash_ack[]     = T7FLA_ACK;
+    char T7_flash_end[]     = T7FLA_END;
     char data[8];
-    int i, k;
-
-    // fopen modified.bin here?
-    // need lots of fcloses though
-    printf("Checking the FLASH BIN file...\r\n");
-    FILE *fp = fopen("/local/modified.bin", "r");    // Open "modified.bin" on the local file system for reading
-    if (!fp) {
-        printf("Error: I could not find the BIN file MODIFIED.BIN\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);
+    printf("Restarting T7 ECU");
+    // Send "Request Data Transfer Exit" to Trionic
+    if (!can_send_timeout (T7SEC_ID, T7_flash_end, 8, T7MESSAGETIMEOUT)) {
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         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);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
-
-    uint32_t address = 0;
-
-    printf("  0.00 %% complete.\r");
-// FLASH main Binary image up to address 0x7B000
-    while (address < 0x70000) {
-        data[0] = 0x40; // 0x40 send, | 0x00 (0) messages to follow
-        data[1] = 0xA1;
-        data[2] = 0x05; // length+1 (4 Bytes)
-        data[3] = 0x36; // Data Transfer
-        for ( k = 4; k < 8; k++ )
-            if (!fread(&data[k],1,1,fp)) {
-                fclose(fp);
-                printf("Error reading the BIN file MODIFIED.BIN\r\n");
-                return FALSE;
-            }
-        if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
-            printf("err t7utils line: %d\r\n", __LINE__ );
-            fclose(fp);
-            return FALSE;
-        }
-        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 );
-    }
-
-    // Send "Request Download - tool to module" to Trionic
-    if (!can_send_timeout (T7SEC_ID, T7_flash_jumpc, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+    if ( data[3] != 0x77 ) {
+        printf("Cannot Update FLASH, message refused.\r\n");
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
-    if (!can_send_timeout (T7SEC_ID, T7_flash_jumpd, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+    //
+    // Send "Request Data Transfer Exit" to Trionic
+    if (!can_send_timeout (T7SEC_ID, T7_flash_exit, 8, T7MESSAGETIMEOUT)) {
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
-        printf("err t7utils line: %d\r\n", __LINE__ );
-        fclose(fp);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         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);
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
         return FALSE;
     }
-
-    address = 0x7FF00;
-    fseek (fp , 0x7FF00 , SEEK_SET);
-
-// FLASH BIN file Header
-    while (address < T7FLASHSIZE) {
-        data[0] = 0x40; // 0x40 send, | 0x00 (0) messages to follow
-        data[1] = 0xA1;
-        data[2] = 0x05; // length+1 (4 Bytes)
-        data[3] = 0x36; // Data Transfer
-        for ( k = 4; k < 8; k++ )
-            if (!fread(&data[k],1,1,fp)) {
-                fclose(fp);
-                printf("Error reading the BIN file MODIFIED.BIN\r\n");
-                return FALSE;
-            }
-        if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
-            printf("err t7utils line: %d\r\n", __LINE__ );
-            fclose(fp);
-            return FALSE;
-        }
-        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 );
+    if ( data[3] != 0x71 ) {
+        printf("err %s line: %d\r\n", __FILE__, __LINE__ );
+        return FALSE;
     }
-
-
-    printf("\n");
-    printf("Restarting T7 ECU");
-/*
-        // 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
+    return true;
+}
diff -r 1775b4b13232 -r 2fbcbebed28c t7utils.h
--- a/t7utils.h	Sat Apr 25 17:07:08 2015 +0000
+++ b/t7utils.h	Sat Apr 23 18:31:40 2016 +0000
@@ -42,6 +42,8 @@
 
 // flash_trionic7
 
+#define T7FLASTRT   {0x41,0xA1,0x08,0x34,0x00,0x00,0x00,0x00}    // Start  = 0x000000
+#define T7FLASIZE   {0x00,0xA1,0x00,0x00,0x00,0x00,0x00,0x00}    // Length = 0x000000
 #define T7FLAJP1A   {0x41,0xA1,0x08,0x34,0x00,0x00,0x00,0x00}    // Start  = 0x000000
 #define T7FLAJP1B   {0x00,0xA1,0x08,0x00,0x00,0x00,0x00,0x00}    // Length = 0x080000
 #define T7FLABINA   {0x41,0xA1,0x08,0x34,0x00,0x00,0x00,0x00}    // Start  = 0x000000
@@ -57,14 +59,17 @@
 #define T7LONGERTIMEOUT 500             // 500 milliseconds (0.5 of a second) - Some messages seem to need longer
 #define T7CHECKSUMTIMEOUT 2000          // 2 seconds (2,000 milliseconds) - Usually takes less than a second so allowing 2 is plenty
 #define T7CONNECTTIMEOUT 5000           // 5 seconds (5,000 milliseconds) - Usually takes 3 seconds so allowing 5 is plenty
-#define T7ERASETIMEOUT 40000            // 40 seconds (60,000 milliseconds) - Usually takes less than 20 seconds so allowing 40 is plenty
+#define T7ERASETIMEOUT 40000            // 40 seconds (40,000 milliseconds) - Usually takes less than 20 seconds so allowing 40 is plenty
 
 extern bool t7_initialise();
 extern bool t7_authenticate();
-extern bool t7_dump();
-extern bool t7_flash();
-extern bool t7_flash_raw();
+extern FILE * t7_file_open(const char* fname);
+extern bool t7_dump(bool blockmode);
 extern bool t7_erase();
+extern bool t7_flash(FILE *, bool blockmode);
+extern bool t7_recover(FILE *);
+bool t7_flash_segment(FILE *, uint32_t address, uint32_t size, bool blockmode);
+extern bool t7_reset();
 /* global constants */
 //#define init_msg        { 0x3F, 0x81, 0x00, 0x11, 0x02, 0x40, 0x00, 0x00 }
 
diff -r 1775b4b13232 -r 2fbcbebed28c t8utils.cpp
--- a/t8utils.cpp	Sat Apr 25 17:07:08 2015 +0000
+++ b/t8utils.cpp	Sat Apr 23 18:31:40 2016 +0000
@@ -361,12 +361,12 @@
     }
     printf("Security Access Granted\r\n");
 //
+// All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance)
 //    const uint8_t BootLoader[] = T8BootloaderProg;
 //    if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, BootLoader))
     if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, T8BootLoaderWrite))
         return FALSE;
 //
-// All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance)
     uint32_t StartAddress = 0x020000;
     uint32_t txpnt = 0;
     char iFrameNumber = 0x21;