Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers t7utils.cpp Source File

t7utils.cpp

00001 /*******************************************************************************
00002 
00003 t7utils.cpp
00004 (c) 2011, 2012 by Sophie Dexter
00005 portions (c) Tomi Liljemark (firstname.surname@gmail.com)
00006 
00007 This C++ module provides functions for communicating simple messages to and from
00008 the T7 ECU
00009 
00010 ********************************************************************************
00011 
00012 WARNING: Use at your own risk, sadly this software comes with no guarantees.
00013 This software is provided 'free' and in good faith, but the author does not
00014 accept liability for any damage arising from its use.
00015 
00016 *******************************************************************************/
00017 
00018 #include "t7utils.h"
00019 
00020 
00021 //
00022 // t7_initialise
00023 //
00024 // sends an initialisation message to the T7 ECU
00025 // but doesn't displays anything.
00026 //
00027 // inputs:    none
00028 // return:    bool TRUE if there was a message, FALSE if no message.
00029 //
00030 
00031 
00032 bool t7_initialise()
00033 {
00034     // send a can message to the T7 requesting that it initialises CAN communication with Just4Trionic
00035     char T7TxMsg[] = T7INITMSG;
00036     if (!can_send_timeout (T7CMNDID, T7TxMsg, 8, T7MESSAGETIMEOUT))
00037         return FALSE;
00038     // wait for the T7 to reply
00039     char T7RxMsg[8];
00040     // if a message is not received, has the wrong id
00041     if (!can_wait_timeout(T7RESPID, T7RxMsg, 8, T7MESSAGETIMEOUT))
00042         return FALSE;
00043     /* DEBUG info...
00044         for (int i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
00045         printf(" init\r\n");
00046     */
00047     return TRUE;
00048 }
00049 
00050 //
00051 // t7_authenticate
00052 //
00053 // sends an authentication message to the T7 ECU
00054 // but doesn't displays anything.
00055 //
00056 // inputs:    none
00057 // return:    bool TRUE if there was a message, FALSE if no message.
00058 //
00059 
00060 bool t7_authenticate()
00061 {
00062     uint16_t seed, key;
00063 //    uint16_t i;
00064     char T7TxAck[] = T7ACK_MSG;
00065     char T7TxMsg[] = T7SEC_MSG;
00066     char T7TxKey[] = T7KEY_MSG;
00067     char T7RxMsg[8];
00068     // Send "Request Seed" to Trionic7
00069     if (!can_send_timeout (T7SEC_ID, T7TxMsg, 8, T7MESSAGETIMEOUT))
00070         return FALSE;
00071     // wait for the T7 to reply
00072     // Read "Seed"
00073     // if a message is not received id return false
00074     if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT))
00075         return FALSE;
00076     /* DEBUG info...
00077         for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
00078         printf(" seed\r\n");
00079     */
00080     // Send Ack
00081     T7TxAck[3] = T7RxMsg[0] & 0xBF;
00082     if (!can_send_timeout (T7ACK_ID, T7TxAck, 8, T7MESSAGETIMEOUT))
00083         return FALSE;
00084     // Send "Key", try two different methods of calculating the key
00085     seed = T7RxMsg[5] << 8 | T7RxMsg[6];
00086     for (int method = 0; method < 2; method++ ) {
00087         key = seed << 2;
00088         key &= 0xFFFF;
00089         key ^= ( method ? 0x4081 : 0x8142 );
00090         key -= ( method ? 0x1F6F : 0x2356 );
00091         key &= 0xFFFF;
00092         T7TxKey[5] = ( key >> 8 ) & 0xFF;
00093         T7TxKey[6] = key & 0xFF;
00094         if (!can_send_timeout (T7SEC_ID, T7TxKey, 8, T7MESSAGETIMEOUT))
00095             return FALSE;
00096         // Wait for response
00097         // if a message is not received id return false
00098         if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT))
00099             return FALSE;
00100         /* DEBUG info...
00101                 for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
00102                 printf(" key %d 0x%02X 0x%02X\r\n", method, T7RxMsg[3], T7RxMsg[5]);
00103         */
00104         // Send Ack
00105         T7TxAck[3] = T7RxMsg[0] & 0xBF;
00106         if (!can_send_timeout (T7ACK_ID, T7TxAck, 8, T7MESSAGETIMEOUT)) {
00107             /* DEBUG info...
00108                         printf("Key ACK message timeout\r\n");
00109             */
00110             return FALSE;
00111         }
00112         if ( T7RxMsg[3] == 0x67 && T7RxMsg[5] == 0x34 ) {
00113             /* DEBUG info...
00114                         printf("Key %d Accepted\r\n", method);
00115             */
00116             return TRUE;
00117         } else {
00118             /* DEBUG info...
00119                         printf("Key %d Failed\r\n", method);
00120             */
00121         }
00122     }
00123     return FALSE;
00124 }
00125 //
00126 // t7_dump
00127 //
00128 // dumps the T7 BIN File
00129 // but doesn't displays anything.
00130 //
00131 // inputs:    none
00132 // return:    bool TRUE if there was a message, FALSE if no message.
00133 //
00134 
00135 bool t7_dump(bool blockmode)
00136 {
00137     uint32_t received;
00138     uint8_t byte_count, retries, i;
00139     char T7_dump_jumpa[] = T7DMPJP1A;
00140     char T7_dump_jumpb[] = T7DMPJP1B;
00141     char T7_dump_ack[] = T7DMP_ACK;
00142     char T7_dump_data[] = T7DMPDATA;
00143     char T7_dump_end[] = T7DMP_END;
00144     char T7RxMsg[8];
00145 
00146     printf("Creating FLASH dump file...\r\n");
00147     FILE *fp = fopen("/local/original.bin", "w");    // Open "original.bin" on the local file system for writing
00148     if (!fp) {
00149         perror ("The following error occured");
00150         return TERM_ERR;
00151     }
00152 
00153     timer.reset();
00154     timer.start();
00155 
00156     received = 0;
00157     printf("  0.00 %% complete.\r");
00158     while (received < T7FLASHSIZE) {
00159 //        T7_dump_jumpa[7] = ((T7FLASHSIZE - received) < 0xEF) ? (T7FLASHSIZE - received) : 0xEF;
00160         T7_dump_jumpb[2] = (received >> 16) & 0xFF;
00161         T7_dump_jumpb[3] = (received >> 8) & 0xFF;
00162         T7_dump_jumpb[4] = received & 0xFF;
00163         // Send read address and length to Trionic
00164         if (!can_send_timeout (T7SEC_ID, T7_dump_jumpa, 8, T7MESSAGETIMEOUT)) {
00165             printf("err t7utils line: %d\r\n", __LINE__ );
00166             fclose(fp);
00167             return FALSE;
00168         }
00169         if (!can_send_timeout (T7SEC_ID, T7_dump_jumpb, 8, T7MESSAGETIMEOUT)) {
00170             printf("err t7utils line: %d\r\n", __LINE__ );
00171             fclose(fp);
00172             return FALSE;
00173         }
00174         // Wait for a response
00175         if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) {
00176             printf("err t7utils line: %d\r\n", __LINE__ );
00177             fclose(fp);
00178             return FALSE;
00179         }
00180         /* DEBUG info...
00181             for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
00182             printf(" seed\r\n");
00183         */
00184         // Send Ack
00185         T7_dump_ack[3] = T7RxMsg[0] & 0xBF;
00186         if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) {
00187             printf("ERROR Asking1: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
00188             printf("err t7utils line: %d\r\n", __LINE__ );
00189             fclose(fp);
00190             return FALSE;
00191         }
00192         if ((T7RxMsg[3] != 0x6C) ||(T7RxMsg[4] != 0xF0)) {
00193             printf("ERROR Asking2: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
00194             printf("err t7utils line: %d\r\n", __LINE__ );
00195             fclose(fp);
00196             return FALSE;
00197         }
00198         // Ask T7 ECU to start sending data
00199         for (retries = 0 ; retries <10 ; retries++ ) {
00200             if (!can_send_timeout (T7SEC_ID, T7_dump_data, 8, T7MESSAGETIMEOUT)) {
00201                 printf("err t7utils line: %d\r\n", __LINE__ );
00202                 fclose(fp);
00203                 return FALSE;
00204             }
00205             // Read mesages from the T7 ECU
00206             byte_count = 0;
00207             T7RxMsg[0] = 0x00;
00208             while (T7RxMsg[0] != 0x80 && T7RxMsg[0] != 0xC0) {
00209                 if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT))
00210                     break;
00211                 // Need to process the received data here!
00212                 // Send Ack
00213                 T7_dump_ack[3] = T7RxMsg[0] & 0xBF;
00214                 if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) {
00215                     printf("ERROR processing: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
00216                     printf("err t7utils line: %d\r\n", __LINE__ );
00217                     fclose(fp);
00218                     return FALSE;
00219                 }
00220 //                /* DEBUG info...
00221 //                for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] );
00222 //                for (i = 2; i < 8; i++ ) printf("%c ", T7RxMsg[i] );
00223 //                printf(" data\r\n");
00224                 for (i = 2; i < 8; i++ )
00225                     file_buffer[byte_count++] = (T7RxMsg[i]);
00226 //                */
00227             }
00228             // Success if these conditions met
00229             if (T7RxMsg[0] == 0x80 || T7RxMsg[0] == 0xC0)
00230                 break;
00231 //            printf("retries: %d\r\n", retries);
00232         }
00233         if (retries > 9) {
00234             printf("err t7utils line: %d\r\n", __LINE__ );
00235             printf("Retries: %d, Done: %5.2f %%\r\n", retries, 100*(float)received/(float)T7FLASHSIZE );
00236             fclose(fp);
00237             return FALSE;
00238         }
00239 //        received += 0xEF;
00240         received += 0x80;
00241 //        printf("Retries: %d, Done: %5.2f %%\r\n", retries, 100*(float)received/(float)T7FLASHSIZE );
00242         printf("%6.2f\r", 100*(float)received/(float)T7FLASHSIZE );
00243         fwrite((file_buffer + 3), 1, 0x80, fp);
00244         if (ferror (fp)) {
00245             fclose (fp);
00246             printf ("Error writing to the FLASH BIN file.\r\n");
00247             return TERM_ERR;
00248         }
00249     }
00250     printf("\n");
00251     // Send Message to T7 ECU to say that we have finished
00252     if (!can_send_timeout (T7SEC_ID, T7_dump_end, 8, T7MESSAGETIMEOUT)) {
00253         fclose(fp);
00254         return FALSE;
00255     }
00256     // Wait for response
00257     if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) {
00258         fclose(fp);
00259         return FALSE;
00260     }
00261 // Send Ack
00262     T7_dump_ack[3] = T7RxMsg[0] & 0xBF;
00263     if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) {
00264         printf("ERROR closing1: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
00265         printf("err t7utils line: %d\r\n", __LINE__ );
00266         fclose(fp);
00267         return FALSE;
00268     }
00269     if (T7RxMsg[3] != 0xC2) {
00270         printf("ERROR closing2: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE);
00271         printf("err t7utils line: %d\r\n", __LINE__ );
00272         fclose(fp);
00273         return FALSE;
00274     }
00275     timer.stop();
00276     printf("SUCCESS! Getting the FLASH dump took %#.1f seconds.\r\n",timer.read());
00277     fclose(fp);
00278     return TRUE;
00279 }
00280 
00281 bool t7_erase()
00282 {
00283     char T7_erase_msga[]    = { 0x40, 0xA1, 0x02, 0x31, 0x52, 0x00, 0x00, 0x00 };
00284     char T7_erase_msgb[]    = { 0x40, 0xA1, 0x02, 0x31, 0x53, 0x00, 0x00, 0x00 };
00285     char T7_erase_confirm[] = { 0x40, 0xA1, 0x01, 0x3E, 0x00, 0x00, 0x00, 0x00 };
00286     char T7_erase_ack[]     = { 0x40, 0xA1, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00 };
00287     char data[8];
00288     int i;
00289 
00290     printf("Erasing T7 ECU FLASH...\r\n");
00291 
00292     data[3] = 0;
00293     i = 0;
00294     while ( data[3] != 0x71 && i < 10) {
00295         // Send "Request to ERASE" to Trionic
00296         if (!can_send_timeout (T7SEC_ID, T7_erase_msga, 8, T7MESSAGETIMEOUT)) {
00297             printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00298             return FALSE;
00299         }
00300         if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00301             printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00302             return FALSE;
00303         }
00304         T7_erase_ack[3] = data[0] & 0xBF;
00305         if (!can_send_timeout (T7ACK_ID, T7_erase_ack, 8, T7MESSAGETIMEOUT)) {
00306             printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00307             return FALSE;
00308         }
00309         wait_ms(100);
00310         i++;
00311         printf(".");
00312     }
00313     printf("\r\n");
00314     // Check to see if erase operation lasted longer than 1 sec...
00315     if (i >=10) {
00316         printf("Second Message took too long'\r\n");
00317         return FALSE;
00318     }
00319     data[3] = 0;
00320     i = 0;
00321     while ( data[3] != 0x71 && i < 200) {
00322         // Send "Request to ERASE" to Trionic
00323         if (!can_send_timeout (T7SEC_ID, T7_erase_msgb, 8, T7MESSAGETIMEOUT)) {
00324             printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00325             return FALSE;
00326         }
00327         if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00328             printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00329             return FALSE;
00330         }
00331         T7_erase_ack[3] = data[0] & 0xBF;
00332         if (!can_send_timeout (T7ACK_ID, T7_erase_ack, 8, T7MESSAGETIMEOUT)) {
00333             printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00334             return FALSE;
00335         }
00336         wait_ms(100);
00337         i++;
00338         printf(".");
00339     }
00340     printf("\r\n");
00341     // Check to see if erase operation lasted longer than 20 sec...
00342     if (i >=200) {
00343         printf("Second Message took too long'\r\n");
00344         return FALSE;
00345     }
00346 
00347     // Confirm erase was successful?
00348     // (Note: no acknowledgements used for some reason)
00349     if (!can_send_timeout (T7SEC_ID, T7_erase_confirm, 8, T7MESSAGETIMEOUT)) {
00350         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00351         return FALSE;
00352     }
00353     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00354         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00355         return FALSE;
00356     }
00357     if ( data[3] != 0x7E ) {
00358         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00359         return FALSE;
00360     }
00361     wait_ms(100);
00362     if (!can_send_timeout (T7SEC_ID, T7_erase_confirm, 8, T7MESSAGETIMEOUT)) {
00363         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00364         return FALSE;
00365     }
00366     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00367         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00368         return FALSE;
00369     }
00370     if ( data[3] != 0x7E ) {
00371         printf("FAILURE: Unable to erase the FLASH .\r\n");
00372         return FALSE;
00373     }
00374     printf("SUCCESS: The FLASH has been erased.\r\n");
00375     return TRUE;
00376 }
00377 
00378 
00379 /// Open and check the bin file to make sure that it is a valid T7 BIN file
00380 ///
00381 /// params  full filename including path of the T7 BIN file
00382 ///
00383 /// returns a pointer to the T7 BIN file
00384 ///         or a null pointer if it is invalid in some way
00385 
00386 FILE * t7_file_open(const char* fname)
00387 {
00388     printf("Checking the FLASH BIN file...\r\n");
00389     FILE *fp = fopen(fname, "r");    // Open "modified.bin" on the local file system for reading
00390     if (!fp) {
00391         printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");;
00392         return NULL;
00393     }
00394     // obtain file size - it should match the size of the FLASH chips:
00395     fseek (fp , 0 , SEEK_END);
00396     uint32_t file_size = ftell (fp);
00397     rewind (fp);
00398     if (file_size != T7FLASHSIZE) {
00399         fclose(fp);
00400         printf("The BIN file does not appear to be for a T7 ECU :-(\r\n");
00401         printf("T7's FLASH chip size is: %#010x bytes.\r\n", T7FLASHSIZE);
00402         printf("The BIN's file size is: %#010x bytes.\r\n", file_size);
00403         return NULL;
00404     }
00405 
00406     // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU
00407     uint8_t stack_byte = 0;
00408     uint32_t stack_long = 0;
00409     for (uint32_t i=0; i<4; i++) {
00410         if (!fread(&stack_byte,1,1,fp)) {
00411             printf("Error reading the BIN file MODIFIED.BIN\r\n");
00412             return NULL;
00413         }
00414         stack_long <<= 8;
00415         stack_long |= stack_byte;
00416     }
00417     rewind (fp);
00418     if (stack_long != T7POINTER) {
00419         fclose(fp);
00420         printf("The BIN file does not appear to be for a T7 ECU :-(\r\n");
00421         printf("A T7 BIN file should start with: %#010x.\r\n", T7POINTER);
00422         printf("This file starts with : %#010x.\r\n", stack_long);
00423         return NULL;
00424     }
00425     printf("The BIN file appears to OK :-)\r\n");
00426     return fp;
00427 }
00428 
00429 
00430 bool t7_flash_segment(FILE *fp, uint32_t address, uint32_t size, bool blockmode)
00431 {
00432     char T7_flash_start[]   = T7FLASTRT;
00433     char T7_flash_size[]    = T7FLASIZE;
00434     char T7_flash_ack[]     = T7FLA_ACK;
00435     char data[8];
00436 
00437     int32_t i, k;
00438 
00439     uint32_t current_address = address;
00440     uint32_t segment_end = address + size;
00441 
00442     if ((current_address > T7FLASHSIZE) || (segment_end > T7FLASHSIZE)) {
00443         printf("Attempting to FLASH outside of FLASH region\r\n");
00444         printf("Start Address: %#010x, End Address: %#010x.\r\n", current_address, segment_end);
00445         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00446         return FALSE;
00447     }
00448 
00449     // blocksize can be any size between 1 and 250 (0x01 - 0xFA)
00450     // Better performance is realised with a bigger blocksize
00451     //
00452     // The following convenient sizes to use for testing
00453     //     0x04, 0x10 and 0x40
00454     // A value of 0x70 is useful when programming the BIN region
00455     //uint32_t blocksize = (blockmode == true) ? 0x70 : 0x04;
00456     uint32_t blocksize = (blockmode == true) ? 0xFA : 0x04;
00457     // Sanity check 
00458     if (blocksize < 0x01) blocksize = 0x01;
00459     if (blocksize > 0xFA) blocksize = 0xFA;
00460     uint32_t blockquantity, blockremainder, blockfirst, blockduring;
00461 
00462     if (fseek (fp , address , SEEK_SET) != 0x0) {
00463         printf("Cannot move to file position %#010x.\r\n", current_address);
00464         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00465         return FALSE;
00466     }
00467     for(i=0; i<3; i++) {
00468         T7_flash_start[6-i] = (address >> (8*i)) & 0xff;
00469         T7_flash_size[4-i] = (size >> (8*i)) & 0xff;
00470     }
00471 
00472     // Send "Request Download - tool to module" to Trionic for the BIN file code and 'cal' data
00473     if (!can_send_timeout (T7SEC_ID, T7_flash_start, 8, T7MESSAGETIMEOUT)) {
00474         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00475         return FALSE;
00476     }
00477     if (!can_send_timeout (T7SEC_ID, T7_flash_size, 8, T7MESSAGETIMEOUT)) {
00478         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00479         return FALSE;
00480     }
00481     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00482         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00483         return FALSE;
00484     }
00485     T7_flash_ack[3] = data[0] & 0xBF;
00486     if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
00487         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00488         return FALSE;
00489     }
00490     if ( data[3] != 0x74 ) {
00491         printf("Cannot Update FLASH, message refused.\r\n");
00492         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00493         return FALSE;
00494     }
00495 
00496 // FLASH main Binary image up to address + size
00497     printf("  0.00 %% complete.\r");
00498     while (current_address < segment_end) {
00499         if ((segment_end - current_address) < blocksize) {
00500             blocksize = (segment_end - current_address);
00501             wait_ms(T7MESSAGETIMEOUT);
00502         }
00503         if (blocksize > 4) {
00504             blockfirst = 4;
00505             blockquantity = (blocksize - blockfirst) / 6;
00506             blockremainder = (blocksize - blockfirst) % 6;
00507             if (blockremainder != 0) {
00508                 blockquantity++;
00509             }
00510         } else {
00511             blockfirst = blocksize;
00512             blockquantity = 0;
00513             blockremainder = 0;
00514         }
00515 
00516         data[0] = 0x40 + blockquantity; // e.g 0x40 send, | 0x0A (10) messages to follow
00517         data[1] = 0xA1;
00518         data[2] = blocksize + 1; // length+1 (64 Bytes)
00519         data[3] = 0x36; // Data Transfer
00520         if (!fread((data+4),1,blockfirst,fp)) {
00521             printf("\nError reading the BIN file MODIFIED.BIN\r\n");
00522             return FALSE;
00523         }
00524 #ifdef DEBUG
00525 // DEBUG info...
00526         for (k = 0; k < 8; k++ ) printf("0x%02X ", data[k] );
00527         for (k = 2; k < 8; k++ ) printf("%c ", data[k] );
00528         printf(" data\r\n");
00529 #endif
00530         if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
00531             printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
00532             return FALSE;
00533         }
00534         if (blocksize > 4) {
00535             for (i = (blockquantity-1); i>=0; i--) {
00536                 data[0] = i;
00537                 if ((i == 0) && (blockremainder != 0)) {
00538                     blockduring = blockremainder;
00539                 } else {
00540                     blockduring = 6;
00541                 }
00542                 if (!fread((data+2),1,blockduring,fp)) {
00543                     printf("\nError reading the BIN file MODIFIED.BIN\r\n");
00544                     return FALSE;
00545                 }
00546 #ifdef DEBUG
00547 //  DEBUG info...
00548                 for (k = 0; k < 8; k++ ) printf("0x%02X ", data[k] );
00549                 for (k = 2; k < 8; k++ ) printf("%c ", data[k] );
00550                 printf(" data\r\n");
00551                 printf("%6.2f\r", 100*(float)current_address/(float)T7FLASHSIZE );
00552 #endif
00553                 wait_us(300);
00554 //                wait_ms(10);   // 31/3/12 this longer wait might be needed for i-bus connections...
00555                 if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) {
00556                     printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
00557                     return FALSE;
00558                 }
00559             }
00560         }
00561         if (!can_wait_timeout(T7SEC_RX, data, 8, T7LONGERTIMEOUT)) {
00562             printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
00563             return FALSE;
00564         }
00565         // Send acknowledgement
00566         T7_flash_ack[3] = data[0] & 0xBF;
00567         if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
00568             printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
00569             return FALSE;
00570         }
00571         if ( data[3] != 0x76 ) {
00572             printf ("\n");
00573 //#ifdef DEBUG
00574 //  DEBUG info...
00575             for (k = 0; k < 8; k++ ) printf("%#04x ", data[k] );
00576             for (k = 2; k < 8; k++ ) printf("%c ", data[k] );
00577             printf(" data\r\n");
00578 //#endif
00579             printf("Cannot Program Address %#010x.\r\n", current_address);
00580             printf("Block Size %#04x, First %#04x, Quantity %#04x, Remainder %#04x\r\n", blocksize, blockfirst, blockquantity, blockremainder);
00581             printf("\nerr %s line: %d\r\n", __FILE__, __LINE__ );
00582             return FALSE;
00583         }
00584         current_address += blocksize;
00585 //        if (!(current_address % 0x80))
00586             printf("%6.2f\r", 100*(float)current_address/(float)T7FLASHSIZE );
00587     }
00588     if (blockmode == true) wait_ms(T7MESSAGETIMEOUT);
00589     return TRUE;
00590 }
00591 
00592 bool t7_flash(FILE *fp, bool blockmode)
00593 {
00594     timer.reset();
00595     timer.start();
00596     printf("T7 program and caldata\r\n");
00597     if (t7_flash_segment(fp, 0x000000, 0x070000, blockmode)) {              // T7 program and caldata
00598         printf("\nAdaptation data 1\r\n");
00599         if (t7_flash_segment(fp, 0x070000, 0x002000, blockmode)) {          // Adaptation data 1
00600             printf("\nAdaptation data 2\r\n");
00601             if (t7_flash_segment(fp, 0x07C000, 0x00280, blockmode)) {       // Adaptation data 2
00602                 printf("\nT7Suite watermark\r\n");
00603                 if (t7_flash_segment(fp, 0x07FD00, 0x000020, blockmode)) {      // T7Suite watermark
00604                     printf("\nT7 Header\r\n");
00605                     if (t7_flash_segment(fp, 0x07FF00, 0x000100, blockmode)) {  // T7 Header
00606                         timer.stop();
00607                         printf("100.00\r\n");
00608                         printf("SUCCESS! Programming the FLASH took %#.1f seconds.\r\n",timer.read());
00609                         return true;
00610                     }
00611                 }
00612             }
00613         }
00614     }
00615     timer.stop();
00616     printf("\nFAILURE! Unable to program FLASH after %#.1f seconds.\r\n",timer.read());
00617     return false;
00618 }
00619 
00620 bool t7_recover(FILE *fp)
00621 {
00622     timer.reset();
00623     timer.start();
00624     if (t7_flash_segment(fp, 0x000000, 0x080000, false)) {              // Entire T7 BIN File
00625         timer.stop();
00626         printf("100.00\r\n");
00627         printf("SUCCESS! Programming the FLASH took %#.1f seconds.\r\n",timer.read());
00628         return true;
00629     }
00630     timer.stop();
00631     printf("\nFAILURE! Unable to program FLASH after %#.1f seconds.\r\n",timer.read());
00632     return false;
00633 }
00634 
00635 
00636 /// Reset and restart a T7 ECU after a FLASH operation
00637 ///
00638 /// NOTE: DOESN't WORK !!!
00639 ///
00640 bool t7_reset()
00641 {
00642     char T7_flash_exit[]    = T7FLAEXIT;
00643     char T7_flash_ack[]     = T7FLA_ACK;
00644     char T7_flash_end[]     = T7FLA_END;
00645     char data[8];
00646 
00647     printf("Restarting T7 ECU");
00648     // Send "Request Data Transfer Exit" to Trionic
00649     if (!can_send_timeout (T7SEC_ID, T7_flash_end, 8, T7MESSAGETIMEOUT)) {
00650         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00651         return FALSE;
00652     }
00653     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00654         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00655         return FALSE;
00656     }
00657     T7_flash_ack[3] = data[0] & 0xBF;
00658     if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
00659         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00660         return FALSE;
00661     }
00662     if ( data[3] != 0x77 ) {
00663         printf("Cannot Update FLASH, message refused.\r\n");
00664         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00665         return FALSE;
00666     }
00667     //
00668     // Send "Request Data Transfer Exit" to Trionic
00669     if (!can_send_timeout (T7SEC_ID, T7_flash_exit, 8, T7MESSAGETIMEOUT)) {
00670         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00671         return FALSE;
00672     }
00673     if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) {
00674         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00675         return FALSE;
00676     }
00677     T7_flash_ack[3] = data[0] & 0xBF;
00678     if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) {
00679         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00680         return FALSE;
00681     }
00682     if ( data[3] != 0x71 ) {
00683         printf("err %s line: %d\r\n", __FILE__, __LINE__ );
00684         return FALSE;
00685     }
00686     return true;
00687 }