Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers t7can.cpp Source File

t7can.cpp

00001 /*******************************************************************************
00002 
00003 trionic7.cpp - CAN Bus functions for Just4Trionic by Just4pLeisure
00004 (c) 2011, 2012 by Sophie Dexter
00005 
00006 This C++ module provides functions for reading and writing the FLASH chips and
00007 SRAM in Trionic7 ECUs. (Writing the adaption data back to SRAM not done yet).
00008 
00009 Some functions need an additional 'bootloader' program to be sent to the T5 ECU
00010 before they can be used. These functions are: Identifying the T5 ECU type and
00011 FLASH chips, dumping the FLASH chips, erasing the FLASH chips, writing to the
00012 FLASH chips and calculating the FLASH chips' checksum.
00013 
00014 My version of the bootloader, BOOTY.S19, includes some features not in other
00015 bootloaders; identifying the ECU and FLASH chip types, a 'safer' way of dumping
00016 the FLASH chips and the ability to program AMD 29F010 type FLASH chips
00017 
00018 ********************************************************************************
00019 
00020 WARNING: Use at your own risk, sadly this software comes with no guarantees.
00021 This software is provided 'free' and in good faith, but the author does not
00022 accept liability for any damage arising from its use.
00023 
00024 *******************************************************************************/
00025 
00026 #include "t7can.h"
00027 
00028 // constants
00029 #define CMD_BUF_LENGTH      32              ///< command buffer size
00030 
00031 // static variables
00032 static char cmd_buffer[CMD_BUF_LENGTH];     ///< command string buffer
00033 
00034 //static uint32_t cmd_addr;                   ///< address (optional)
00035 //static uint32_t cmd_value;                  ///< value    (optional)
00036 //static uint32_t cmd_result;                 ///< result
00037 
00038 //static uint32_t flash_start = 0;
00039 
00040 // private functions
00041 uint8_t execute_t7_cmd();
00042 void t7_can_show_help();
00043 void t7_can_show_full_help();
00044 
00045 // private variables
00046 bool ibus = false;
00047 bool pbus = false;
00048 
00049 void t7_can()
00050 {
00051     // Start the CAN bus system
00052     // Note that at the moment this is only for T7 ECUs at 500 kbits
00053     t7_can_show_help();
00054 
00055     char data[8];
00056     ibus = false;
00057     pbus = false;
00058     printf("Trying to listen to CAN I-Bus (47619 Bit/s)...\r\n");
00059     can_configure(2, 47619, 1);
00060     if (can_wait_timeout(T7ANYMSG, data, 8, T7MESSAGETIMEOUT)) {
00061         printf("Connected to Saab I-Bus\r\n");
00062         printf("Switching to I-Bus active mode\r\n");
00063         can_configure(2, 47619, 0);
00064         ibus = true;
00065     } else {
00066         printf("I did not receive any I-Bus messages\r\n");
00067         printf("Trying to listen to  CAN P-Bus (500 kBit/s)...\r\n");
00068         can_configure(2, 500000, 1);
00069         if (can_wait_timeout(T7ANYMSG, data, 8, T7MESSAGETIMEOUT)) {
00070             printf("Connected to Saab P-Bus\r\n");
00071             printf("Switching to P-Bus active mode\r\n");
00072             can_configure(2, 500000, 0);
00073             pbus = true;
00074         } else {
00075             printf("I did not receive any P-Bus messages\r\n");
00076             printf("Switching to P-Bus active mode\r\n");
00077             can_configure(2, 500000, 0);
00078             if (can_wait_timeout(T7ANYMSG, data, 8, T7CONNECTTIMEOUT)) {
00079                 printf("Connected to Saab P-Bus\r\n");
00080                 pbus = true;
00081                 //can_active();
00082             } else {
00083                 printf("FAILED to connect!\r\n");
00084                 led4 = 1;
00085             }
00086         }
00087     }
00088 
00089 //    if (t7_initialise())
00090 //        printf("Connected to Saab I-Bus\r\n");
00091 //    else {
00092 //        printf("Opening CAN channel to Saab P-Bus (500 kBit/s)...\r\n");
00093 //        can_set_speed(500000);
00094 //        if (t7_initialise())
00095 //            printf("Connected to Saab P-Bus\r\n");
00096 //        else {
00097 //            printf("FAILED to connect!\r\n");
00098 //            led4 = 1;
00099 //        }
00100 //    }
00101 
00102 //    if (t7_initialise())
00103 //        printf("Trionic 7 Connection OK\r\n");
00104 //    else
00105 //        printf("Trionic 7 Connection Failed\r\n");
00106 //    t7_authenticate();
00107 //    if (t7_authenticate())
00108 //        printf("Security Key Accepted\r\n");
00109 //    else
00110 //        printf("Security Key Failed\r\n");
00111 
00112 // main loop
00113     *cmd_buffer = '\0';
00114     char ret;
00115     char rx_char;
00116     while (true) {
00117         // read chars from USB
00118         // send received messages to the pc over USB connection
00119         // This function displays any CAN messages that are 'missed' by the other functions
00120         // Can messages might be 'missed' because they are received after a 'timeout' period
00121         // or because they weren't expected, e.g. if the T5 ECU resets for some reason
00122 //        t7_show_can_message();
00123         silent_can_message();
00124         if (pc.readable()) {
00125             // turn Error LED off for next command
00126             led4 = 0;
00127             rx_char = pc.getc();
00128             switch (rx_char) {
00129                     // 'ESC' key to go back to mbed Just4Trionic 'home' menu
00130                 case '\e':
00131                     can_close();
00132                     return;
00133                     // end-of-command reached
00134                 case TERM_OK :
00135                     // execute command and return flag via USB
00136                     timer.reset();
00137                     timer.start();
00138                     ret = execute_t7_cmd();
00139                     pc.putc(ret);
00140                     printf("Completed in %.3f seconds.\r\n", timer.read());
00141                     // reset command buffer
00142                     *cmd_buffer = '\0';
00143                     // light up LED
00144                     //                    ret == TERM_OK ? led_on(LED_ACT) : led_on(LED_ERR);
00145                     ret == TERM_OK ? led3 = 1 : led4 = 1;
00146                     break;
00147                     // another command char
00148                 default:
00149                     // store in buffer if space permits
00150                     if (StrLen(cmd_buffer) < CMD_BUF_LENGTH - 1) {
00151                         StrAddc(cmd_buffer, rx_char);
00152                     }
00153                     break;
00154             }
00155         }
00156     }
00157 }
00158 
00159 //-----------------------------------------------------------------------------
00160 /**
00161     Executes a command and returns result flag (does not transmit the flag
00162     itself).
00163 
00164     @return                    command flag (success / failure)
00165 */
00166 uint8_t execute_t7_cmd()
00167 {
00168 
00169 //    uint8_t cmd_length = strlen(cmd_buffer);
00170     // command groups
00171     switch (*cmd_buffer) {
00172 //            CHECK_ARGLENGTH(0);
00173         // Initialise a T7 CAN session
00174         case 'i' :
00175             if (t7_initialise()) {
00176                 printf("SUCCESS! Trionic 7 CAN Connection OK.\r\n");
00177                 return TERM_OK;
00178             } else {
00179                 printf("FAILURE! No CAN connection to Trionic 7.\\r\n");
00180                 return TERM_ERR;
00181             }
00182         // Get security clearance for T7 CAN session
00183         case 'a' :
00184             if (t7_authenticate()) {
00185                 printf("SUCCESS! Security Key Accepted.\r\n");
00186                 return TERM_OK;
00187             } else {
00188                 printf("FAILURE! Unable to obtain a Security Key.\\r\n");
00189                 return TERM_ERR;
00190             }
00191         // Erase the FLASH chips
00192         case 'e':
00193             return t7_erase()
00194                    ? TERM_OK : TERM_ERR;
00195         // DUMP the T5 ECU BIN file stored in the FLASH chips
00196         case 'D':
00197             if (!t7_authenticate()) {
00198                 if (!t7_initialise()) {
00199                     printf("FAILURE! No CAN connection to Trionic 7.\r\n");
00200                     return TERM_ERR;
00201                 }
00202                 if (!t7_authenticate()) {
00203                     printf("FAILURE! Unable to obtain a Security Key.\r\n");
00204                     return TERM_ERR;
00205                 }
00206             }
00207         case 'd':
00208             return t7_dump(pbus)
00209                    ? TERM_OK : TERM_ERR;
00210 // Send a FLASH update file to the T5 ECU
00211         case 'F': {
00212             FILE *fp = t7_file_open("/local/modified.bin");    // Open "modified.bin" on the local file system
00213             if (!fp) {
00214                 printf("FAILURE! Unable to find the BIN file \"MODIFIED.BIN\"\r\n");
00215                 return TERM_ERR;
00216             }
00217             if (!t7_authenticate()) {
00218                 if (!t7_initialise()) {
00219                     printf("FAILURE! No CAN connection to Trionic 7.\r\n");
00220                     fclose(fp);
00221                     return TERM_ERR;
00222                 }
00223                 if (!t7_authenticate()) {
00224                     printf("FAILURE! Unable to obtain a Security Key.\r\n");
00225                     fclose(fp);
00226                     return TERM_ERR;
00227                 }
00228             }
00229             if (!t7_erase()) {
00230                 printf("FAILURE: Unable to Erase FLASH!\r\n");
00231                 fclose(fp);
00232                 return TERM_ERR;
00233             }
00234             bool result = t7_flash(fp, pbus);
00235             fclose(fp);
00236             return result ? TERM_OK : TERM_ERR;
00237         }
00238         case 'f': {
00239             FILE *fp = t7_file_open("/local/modified.bin");    // Open "modified.bin" on the local file system
00240             if (!fp) {
00241                 printf("FAILURE! Unable to find the BIN file \"MODIFIED.BIN\"\r\n");
00242                 return TERM_ERR;
00243             }
00244             bool result = t7_flash(fp, pbus);
00245             fclose(fp);
00246             return result ? TERM_OK : TERM_ERR;
00247         }
00248 // Recovery FLASHes the entire BIN file and using 'safe' but slow 4 byte at a time transfers
00249         case 'R': {
00250             FILE *fp = t7_file_open("/local/modified.bin");    // Open "modified.bin" on the local file system
00251             if (!fp) {
00252                 printf("FAILURE! Unable to find the BIN file \"MODIFIED.BIN\"\r\n");
00253                 return TERM_ERR;
00254             }
00255             if (!t7_authenticate()) {
00256                 if (!t7_initialise()) {
00257                     printf("FAILURE! No CAN connection to Trionic 7.\r\n");
00258                     fclose(fp);
00259                     return TERM_ERR;
00260                 }
00261                 if (!t7_authenticate()) {
00262                     printf("FAILURE! Unable to obtain a Security Key.\r\n");
00263                     fclose(fp);
00264                     return TERM_ERR;
00265                 }
00266             }
00267             if (!t7_erase()) {
00268                 printf("FAILURE: Unable to Erase FLASH!\r\n");
00269                 fclose(fp);
00270                 return TERM_ERR;
00271             }
00272             bool result = t7_recover(fp);
00273             fclose(fp);
00274             return result ? TERM_OK : TERM_ERR;
00275         }
00276 // Try to connect to CAN I-BUS
00277         case 'I' : {
00278             char data[8];
00279             printf("Trying to open CAN I-Bus (47619 Bit/s)...\r\n");
00280             ibus = true;
00281             pbus = false;
00282             can_close();
00283             //can_monitor();
00284             can_set_speed(47619);
00285             can_open();
00286             if (can_wait_timeout(T7ANYMSG, data, 8, T7CONNECTTIMEOUT)) {
00287                 printf("SUCCESS! Connected to Saab I-Bus.\r\n");
00288                 //can_active();
00289                 return TERM_OK;
00290             } else {
00291                 printf("I did not receive any I-Bus messages\r\n");
00292                 printf("FAILURE! Unable to connect Saab I-Bus.\r\n");
00293                 return TERM_ERR;
00294             }
00295         }
00296 // Try to connect to CAN P-BUS
00297         case 'P' : {
00298             char data[8];
00299             printf("Trying to open CAN P-Bus (500 kBit/s)...\r\n");
00300             ibus = false;
00301             pbus = true;
00302             can_close();
00303             //can_monitor();
00304             can_set_speed(500000);
00305             can_open();
00306             if (can_wait_timeout(T7ANYMSG, data, 8, T7CONNECTTIMEOUT)) {
00307                 printf("SUCCESS! Connected to Saab P-Bus.\r\n");
00308                 //can_active();
00309                 return TERM_OK;
00310             } else {
00311                 printf("I did not receive any P-Bus messages\r\n");
00312                 printf("FAILURE! Unable to connect Saab P-Bus.\r\n");
00313                 return TERM_ERR;
00314             }
00315         }
00316 // Print help
00317         case 'h':
00318             t7_can_show_help();
00319             return TERM_OK;
00320         case 'H':
00321             t7_can_show_full_help();
00322             return TERM_OK;
00323         default:
00324             t7_can_show_help();
00325             break;
00326     }
00327 // unknown command
00328     return TERM_ERR;
00329 }
00330 
00331 //
00332 // Trionic7ShowHelp
00333 //
00334 // Displays a list of things that can be done with the T5 ECU.
00335 //
00336 // inputs:    none
00337 // return:    none
00338 //
00339 void t7_can_show_help()
00340 {
00341     printf("Trionic 7 Command Menu\r\n");
00342     printf("======================\r\n");
00343     printf("D - DUMP the T7 ECU FLASH to a file 'ORIGINAL.BIN'\r\n");
00344     printf("F - FLASH the update file 'MODIFIED.BIN' to the T7\r\n");
00345     printf("R - Recovery FLASH T7 with update file 'MODIFIED.BIN'\r\n");
00346     printf("\r\n");
00347     printf("I - Try to open CAN I-Bus (47619 Bit/s)\r\n");
00348     printf("P - Try to open CAN P-Bus (500 kBit/s)\r\n");
00349     printf("\r\n");
00350     printf("'ESC' - Return to Just4Trionic Main Menu\r\n");
00351     printf("\r\n");
00352     printf("h  - Show this help menu\r\n");
00353     printf("\r\n");
00354     return;
00355 }
00356 //
00357 // t7_can_show_full_help
00358 //
00359 // Displays a complete list of things that can be done with the T5 ECU.
00360 //
00361 // inputs:    none
00362 // return:    none
00363 //
00364 void t7_can_show_full_help()
00365 {
00366     printf("Trionic 7 Command Menu\r\n");
00367     printf("======================\r\n");
00368     printf("D - DUMP the T7 ECU FLASH to a file 'ORIGINAL.BIN'\r\n");
00369     printf("F - FLASH the update file 'MODIFIED.BIN' to the T7\r\n");
00370     printf("R - Recovery FLASH T7 with update file 'MODIFIED.BIN'\r\n");
00371     printf("\r\n");
00372     printf("I - Try to open CAN I-Bus (47619 Bit/s)\r\n");
00373     printf("P - Try to open CAN P-Bus (500 kBit/s)\r\n");
00374     printf("\r\n");
00375     printf("\r\n");
00376     printf("i - Send initialisation message to T7\r\n");
00377     printf("a - Send Authentication key to T7\r\n");
00378     printf("d - Dump T7 Bin file 'ORIGINAL.BIN'\r\n");
00379     printf("e - Erase the FLASH in the T7 ECU\r\n");
00380     printf("f - FLASH the file 'MODIFIED.BIN' to the T7 ECU\r\n");
00381     printf("\r\n");
00382     printf("'ESC' - Return to Just4Trionic Main Menu\r\n");
00383     printf("\r\n");
00384     printf("H  - Show this help menu\r\n");
00385     printf("\r\n");
00386     return;
00387 }
00388 
00389