Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Trionic5.cpp@0:e0b964252a05, 2010-05-19 (annotated)
- Committer:
- Just4pLeisure
- Date:
- Wed May 19 12:39:18 2010 +0000
- Revision:
- 0:e0b964252a05
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Just4pLeisure | 0:e0b964252a05 | 1 | /******************************************************************************* |
Just4pLeisure | 0:e0b964252a05 | 2 | |
Just4pLeisure | 0:e0b964252a05 | 3 | Trionic5.cpp - By Sophie Dexter, April 2010 |
Just4pLeisure | 0:e0b964252a05 | 4 | |
Just4pLeisure | 0:e0b964252a05 | 5 | This C++ module provides functions for reading and writing the FLASH chips and |
Just4pLeisure | 0:e0b964252a05 | 6 | SRAM in Trionic5 ECUs. (Writing the adaption data back to SRAM not done yet). |
Just4pLeisure | 0:e0b964252a05 | 7 | |
Just4pLeisure | 0:e0b964252a05 | 8 | Some functions need an additional 'bootloader' program to be sent to the T5 ECU |
Just4pLeisure | 0:e0b964252a05 | 9 | before they can be used. These functions are: Identifying the T5 ECU type and |
Just4pLeisure | 0:e0b964252a05 | 10 | FLASH chips, dumping the FLASH chips, erasing the FLASH chips, writing to the |
Just4pLeisure | 0:e0b964252a05 | 11 | FLASH chips and calculating the FLASH chips' checksum. |
Just4pLeisure | 0:e0b964252a05 | 12 | |
Just4pLeisure | 0:e0b964252a05 | 13 | My version of the bootloader, BOOTY.S19, includes some features not in other |
Just4pLeisure | 0:e0b964252a05 | 14 | bootloaders; identifying the ECU and FLASH chip types, a 'safer' way of dumping |
Just4pLeisure | 0:e0b964252a05 | 15 | the FLASH chips and the ability to program AMD 29F010 type FLASH chips (NOTE |
Just4pLeisure | 0:e0b964252a05 | 16 | that AMD 29F010 FLASH programming is experimental at this stage to say the least) |
Just4pLeisure | 0:e0b964252a05 | 17 | |
Just4pLeisure | 0:e0b964252a05 | 18 | ******************************************************************************** |
Just4pLeisure | 0:e0b964252a05 | 19 | |
Just4pLeisure | 0:e0b964252a05 | 20 | WARNING: Use at your own risk, sadly this software comes with no guarantees. |
Just4pLeisure | 0:e0b964252a05 | 21 | This software is provided 'free' and in good faith, but the author does not |
Just4pLeisure | 0:e0b964252a05 | 22 | accept liability for any damage arising from its use. |
Just4pLeisure | 0:e0b964252a05 | 23 | |
Just4pLeisure | 0:e0b964252a05 | 24 | *******************************************************************************/ |
Just4pLeisure | 0:e0b964252a05 | 25 | |
Just4pLeisure | 0:e0b964252a05 | 26 | #include "Trionic5.h" |
Just4pLeisure | 0:e0b964252a05 | 27 | |
Just4pLeisure | 0:e0b964252a05 | 28 | // RS232 on USB connection |
Just4pLeisure | 0:e0b964252a05 | 29 | Serial pc2(USBTX, USBRX); // tx, rx |
Just4pLeisure | 0:e0b964252a05 | 30 | |
Just4pLeisure | 0:e0b964252a05 | 31 | // A timer for timing how long things take to happen |
Just4pLeisure | 0:e0b964252a05 | 32 | Timer timer; |
Just4pLeisure | 0:e0b964252a05 | 33 | |
Just4pLeisure | 0:e0b964252a05 | 34 | // We use CAN on mbed pins 29(CAN_TXD) and 30(CAN_RXD). |
Just4pLeisure | 0:e0b964252a05 | 35 | CAN can_temp(p30, p29); |
Just4pLeisure | 0:e0b964252a05 | 36 | |
Just4pLeisure | 0:e0b964252a05 | 37 | // Need to create this to be able to read and write files on the mbed 'disk' |
Just4pLeisure | 0:e0b964252a05 | 38 | LocalFileSystem local("local"); |
Just4pLeisure | 0:e0b964252a05 | 39 | |
Just4pLeisure | 0:e0b964252a05 | 40 | void Trionic5() { |
Just4pLeisure | 0:e0b964252a05 | 41 | // Start the CAN bus system |
Just4pLeisure | 0:e0b964252a05 | 42 | // Note that at the moment this is only for T5 ECUs at 615 kbits |
Just4pLeisure | 0:e0b964252a05 | 43 | CANOpen(); |
Just4pLeisure | 0:e0b964252a05 | 44 | |
Just4pLeisure | 0:e0b964252a05 | 45 | int counter = 0; //counter used for testing things !?! |
Just4pLeisure | 0:e0b964252a05 | 46 | |
Just4pLeisure | 0:e0b964252a05 | 47 | Trionic5ShowHelp(); |
Just4pLeisure | 0:e0b964252a05 | 48 | |
Just4pLeisure | 0:e0b964252a05 | 49 | while (1) { |
Just4pLeisure | 0:e0b964252a05 | 50 | // send received messages to the pc over USB connection |
Just4pLeisure | 0:e0b964252a05 | 51 | // This function displays any CAN messages that are 'missed' by the other functions |
Just4pLeisure | 0:e0b964252a05 | 52 | // Can messages might be 'missed' because they are received after a 'timeout' period |
Just4pLeisure | 0:e0b964252a05 | 53 | // or because they weren't expected, e.g. if the T5 ECU resets for some reason |
Just4pLeisure | 0:e0b964252a05 | 54 | Trionic5ShowCANMessage(); |
Just4pLeisure | 0:e0b964252a05 | 55 | |
Just4pLeisure | 0:e0b964252a05 | 56 | // Wait for a single command character from the PC |
Just4pLeisure | 0:e0b964252a05 | 57 | if (pc2.readable()) { |
Just4pLeisure | 0:e0b964252a05 | 58 | // char command[30] = "w0068c600000000000000"; |
Just4pLeisure | 0:e0b964252a05 | 59 | // command = pc2.gets(); |
Just4pLeisure | 0:e0b964252a05 | 60 | char c = (pc2.getc()); |
Just4pLeisure | 0:e0b964252a05 | 61 | if ((c=='h') || (c=='H')) Trionic5ShowHelp(); // Print help |
Just4pLeisure | 0:e0b964252a05 | 62 | if (c=='\e') return; // 'ESC' key to go back to mbed CAN tool menu |
Just4pLeisure | 0:e0b964252a05 | 63 | // if ((c=='s') or (c=='S')) { |
Just4pLeisure | 0:e0b964252a05 | 64 | if (c=='s') Trionic5GetSymbolTable(); // Get the Symbol Table |
Just4pLeisure | 0:e0b964252a05 | 65 | if (c=='S') T5ReadCmnd(T5SYMBOLS); |
Just4pLeisure | 0:e0b964252a05 | 66 | // if ((c=='v') or (c=='V')) { |
Just4pLeisure | 0:e0b964252a05 | 67 | if (c=='v') Trionic5GetVersion(); // Get the Trionic5 software version string |
Just4pLeisure | 0:e0b964252a05 | 68 | if (c=='V') T5ReadCmnd(T5VERSION); |
Just4pLeisure | 0:e0b964252a05 | 69 | // if ((c=='r') or (c=='R')) { |
Just4pLeisure | 0:e0b964252a05 | 70 | if (c=='r') Trionic5GetAdaptionData(); // Read Adaption Data from RAM and write it to a file |
Just4pLeisure | 0:e0b964252a05 | 71 | if (c=='R') T5RAMCmnd(counter++); |
Just4pLeisure | 0:e0b964252a05 | 72 | if (c=='\r') T5ReadCmnd(CR); // CR - send CR type message |
Just4pLeisure | 0:e0b964252a05 | 73 | |
Just4pLeisure | 0:e0b964252a05 | 74 | // if ((c=='a') or (c=='A')) { |
Just4pLeisure | 0:e0b964252a05 | 75 | if (c=='a') { // Get a single symbol from the Symbol Table |
Just4pLeisure | 0:e0b964252a05 | 76 | char symbol[40]; |
Just4pLeisure | 0:e0b964252a05 | 77 | T5GetSymbol(symbol); |
Just4pLeisure | 0:e0b964252a05 | 78 | printf("%s",symbol); |
Just4pLeisure | 0:e0b964252a05 | 79 | } |
Just4pLeisure | 0:e0b964252a05 | 80 | if (c=='A') T5Ack(); // Just send an 'ACK' message |
Just4pLeisure | 0:e0b964252a05 | 81 | if ((c=='b') or (c=='B')) Trionic5SendBootLoader(); // Send a Bootloader file to the T5 ECU |
Just4pLeisure | 0:e0b964252a05 | 82 | if ((c=='c') or (c=='C')) Trionic5GetChecksum(); // Get Checksum from ECU (Bootloader must be uploaded first) |
Just4pLeisure | 0:e0b964252a05 | 83 | if ((c=='q') or (c=='Q')) Trionic5BootloaderReset(); // Exit the BootLoader and restart the T5 ECU |
Just4pLeisure | 0:e0b964252a05 | 84 | if ((c=='e') or (c=='E')) Trionic5EraseFLASH(); // Erase the FLASH chips |
Just4pLeisure | 0:e0b964252a05 | 85 | if ((c=='t') or (c=='T')) Trionic5GetChipTypes(); // Read back the FLASH chip types |
Just4pLeisure | 0:e0b964252a05 | 86 | // if ((c=='d') or (c=='D')) Trionic5DumpFLASH(); // DUMP the T5 ECU BIN file stored in the FLASH chips |
Just4pLeisure | 0:e0b964252a05 | 87 | // if (c=='d') Trionic5DumpFLASH(); // DUMP the T5 ECU BIN file stored in the FLASH chips |
Just4pLeisure | 0:e0b964252a05 | 88 | // if (c=='D') Trionic5DumpFLASH2(); // DUMP the T5 ECU BIN file stored in the FLASH chips |
Just4pLeisure | 0:e0b964252a05 | 89 | if ((c=='d') or (c=='D')) Trionic5DumpFLASH2(); // DUMP the T5 ECU BIN file stored in the FLASH chips |
Just4pLeisure | 0:e0b964252a05 | 90 | if ((c=='f') or (c=='F')) Trionic5SendFLASHUpdate(); // Send a FLASH update file to the T5 ECU |
Just4pLeisure | 0:e0b964252a05 | 91 | if (c=='3') Trionic5SendC3Message(); // Send the C3 message - should get last used address 0x7FFFF |
Just4pLeisure | 0:e0b964252a05 | 92 | } |
Just4pLeisure | 0:e0b964252a05 | 93 | } |
Just4pLeisure | 0:e0b964252a05 | 94 | } |
Just4pLeisure | 0:e0b964252a05 | 95 | |
Just4pLeisure | 0:e0b964252a05 | 96 | // |
Just4pLeisure | 0:e0b964252a05 | 97 | // Trionic5ShowHelp |
Just4pLeisure | 0:e0b964252a05 | 98 | // |
Just4pLeisure | 0:e0b964252a05 | 99 | // Displays a list of things that can be done with the T5 ECU. |
Just4pLeisure | 0:e0b964252a05 | 100 | // |
Just4pLeisure | 0:e0b964252a05 | 101 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 102 | // return: none |
Just4pLeisure | 0:e0b964252a05 | 103 | // |
Just4pLeisure | 0:e0b964252a05 | 104 | void Trionic5ShowHelp() { |
Just4pLeisure | 0:e0b964252a05 | 105 | printf("Trionic 5 Command Menu\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 106 | printf("======================\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 107 | printf("b - upload and start MyBooty.S19 bootloader\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 108 | printf("c - get T5 ECU FLASH checksum (need toupload BOOTY.S19 before using this command)\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 109 | printf("d - dump the T5 FLASH BIN file and write it to ORIGINAL.HEX\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 110 | printf("e - erase the FLASH chips in the T5 ECU\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 111 | printf("f - FLASH the upate file MODIFIED.S19 to the T5 ECU\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 112 | printf("e - erase the FLASH chips in the T5 ECU\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 113 | printf("r - read SRAM and write it to ADAPTION.HEX file\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 114 | printf("s - read Symbol Table, display it and write it to SYMBOLS.TXT\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 115 | printf("v - read T5 ECU software version, display it and write it to VERSION.TXT\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 116 | printf("q - exit the bootloader and reset the T5 ECU\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 117 | printf("t - read the FLASH chip type in the T5 ECU\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 118 | printf("3 - read the last used FLASH address in the T5 ECU\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 119 | printf("S - send 's' message (to get symbol table)\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 120 | printf("V - send 'S' message (to get software version)\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 121 | printf("'Enter' Key - send an CR message\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 122 | printf("a - send an ACK\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 123 | printf("A - read a single symbol from the symbol table\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 124 | printf("\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 125 | printf("'ESC' - return to mbed CAN tool Menu\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 126 | printf("\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 127 | printf("h/H - show this help menu\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 128 | return; |
Just4pLeisure | 0:e0b964252a05 | 129 | } |
Just4pLeisure | 0:e0b964252a05 | 130 | |
Just4pLeisure | 0:e0b964252a05 | 131 | // |
Just4pLeisure | 0:e0b964252a05 | 132 | // Trionic5ShowCANMessage |
Just4pLeisure | 0:e0b964252a05 | 133 | // |
Just4pLeisure | 0:e0b964252a05 | 134 | // Displays a CAN message in the RX buffer if there is one. |
Just4pLeisure | 0:e0b964252a05 | 135 | // |
Just4pLeisure | 0:e0b964252a05 | 136 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 137 | // return: bool TRUE if there was a message, FALSE if no message. |
Just4pLeisure | 0:e0b964252a05 | 138 | // |
Just4pLeisure | 0:e0b964252a05 | 139 | bool Trionic5ShowCANMessage() { |
Just4pLeisure | 0:e0b964252a05 | 140 | CANMessage can_MsgRx; |
Just4pLeisure | 0:e0b964252a05 | 141 | if (can_temp.read(can_MsgRx)) { |
Just4pLeisure | 0:e0b964252a05 | 142 | printf("w%03x%d", can_MsgRx.id, can_MsgRx.len); |
Just4pLeisure | 0:e0b964252a05 | 143 | for (char i=0; i<can_MsgRx.len; i++) { |
Just4pLeisure | 0:e0b964252a05 | 144 | printf("%02x", can_MsgRx.data[i]); |
Just4pLeisure | 0:e0b964252a05 | 145 | } |
Just4pLeisure | 0:e0b964252a05 | 146 | printf(" %c ", can_MsgRx.data[2]); |
Just4pLeisure | 0:e0b964252a05 | 147 | printf("\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 148 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 149 | } |
Just4pLeisure | 0:e0b964252a05 | 150 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 151 | } |
Just4pLeisure | 0:e0b964252a05 | 152 | |
Just4pLeisure | 0:e0b964252a05 | 153 | // |
Just4pLeisure | 0:e0b964252a05 | 154 | // Trionic5GetSymbolTable |
Just4pLeisure | 0:e0b964252a05 | 155 | // |
Just4pLeisure | 0:e0b964252a05 | 156 | // Gets the T5 ECU symbol table. |
Just4pLeisure | 0:e0b964252a05 | 157 | // The Symbol Table is sent to the PC and saved to a file, symbols.txt, on the mbed 'local' file system 'disk'. |
Just4pLeisure | 0:e0b964252a05 | 158 | // |
Just4pLeisure | 0:e0b964252a05 | 159 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 160 | // return: bool TRUE if there all went OK, FALSE if there was an error |
Just4pLeisure | 0:e0b964252a05 | 161 | // |
Just4pLeisure | 0:e0b964252a05 | 162 | bool Trionic5GetSymbolTable() { |
Just4pLeisure | 0:e0b964252a05 | 163 | FILE *fp = fopen("/local/symbols.txt", "w"); // Open "symbols.txt" on the local file system for writing |
Just4pLeisure | 0:e0b964252a05 | 164 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 165 | char symbol[40]; |
Just4pLeisure | 0:e0b964252a05 | 166 | char response = '\0'; |
Just4pLeisure | 0:e0b964252a05 | 167 | T5ReadCmnd(T5SYMBOLS); |
Just4pLeisure | 0:e0b964252a05 | 168 | response = T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 169 | if (response != '>') |
Just4pLeisure | 0:e0b964252a05 | 170 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 171 | // printf("%c",response); |
Just4pLeisure | 0:e0b964252a05 | 172 | T5ReadCmnd(CR); |
Just4pLeisure | 0:e0b964252a05 | 173 | response = T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 174 | if (response != '>') |
Just4pLeisure | 0:e0b964252a05 | 175 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 176 | // printf("%c",response); |
Just4pLeisure | 0:e0b964252a05 | 177 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 178 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 179 | do { |
Just4pLeisure | 0:e0b964252a05 | 180 | T5GetSymbol(symbol); |
Just4pLeisure | 0:e0b964252a05 | 181 | printf("%s",symbol); |
Just4pLeisure | 0:e0b964252a05 | 182 | fprintf(fp,"%s",symbol); |
Just4pLeisure | 0:e0b964252a05 | 183 | } while (!StrCmp(symbol,"END\r\n")); |
Just4pLeisure | 0:e0b964252a05 | 184 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 185 | printf("Getting the Symbol Table took %f seconds.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 186 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 187 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 188 | } |
Just4pLeisure | 0:e0b964252a05 | 189 | |
Just4pLeisure | 0:e0b964252a05 | 190 | // |
Just4pLeisure | 0:e0b964252a05 | 191 | // Trionic5GetVersion |
Just4pLeisure | 0:e0b964252a05 | 192 | // |
Just4pLeisure | 0:e0b964252a05 | 193 | // Gets the T5 software version string. |
Just4pLeisure | 0:e0b964252a05 | 194 | // The software version is is sent to the PC and saved to a file, version.txt, on the mbed 'local' file system 'disk'. |
Just4pLeisure | 0:e0b964252a05 | 195 | // |
Just4pLeisure | 0:e0b964252a05 | 196 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 197 | // return: bool TRUE if there all went OK, FALSE if there was an error |
Just4pLeisure | 0:e0b964252a05 | 198 | // |
Just4pLeisure | 0:e0b964252a05 | 199 | bool Trionic5GetVersion() { |
Just4pLeisure | 0:e0b964252a05 | 200 | FILE *fp = fopen("/local/version.txt", "w"); // Open "version.txt" on the local file system for writing |
Just4pLeisure | 0:e0b964252a05 | 201 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 202 | char symbol[40]; |
Just4pLeisure | 0:e0b964252a05 | 203 | char response = '\0'; |
Just4pLeisure | 0:e0b964252a05 | 204 | T5ReadCmnd(T5VERSION); |
Just4pLeisure | 0:e0b964252a05 | 205 | response = T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 206 | if (response != '>') |
Just4pLeisure | 0:e0b964252a05 | 207 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 208 | // printf("%c",response); |
Just4pLeisure | 0:e0b964252a05 | 209 | T5ReadCmnd(CR); |
Just4pLeisure | 0:e0b964252a05 | 210 | response = T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 211 | if (response != '>') |
Just4pLeisure | 0:e0b964252a05 | 212 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 213 | // printf("%c",response); |
Just4pLeisure | 0:e0b964252a05 | 214 | T5GetSymbol(symbol); |
Just4pLeisure | 0:e0b964252a05 | 215 | printf("%s",symbol); |
Just4pLeisure | 0:e0b964252a05 | 216 | if (fp) |
Just4pLeisure | 0:e0b964252a05 | 217 | fprintf(fp,"%s",symbol); |
Just4pLeisure | 0:e0b964252a05 | 218 | else |
Just4pLeisure | 0:e0b964252a05 | 219 | printf("ERROR Could not open version.txt for saving\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 220 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 221 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 222 | } |
Just4pLeisure | 0:e0b964252a05 | 223 | |
Just4pLeisure | 0:e0b964252a05 | 224 | // |
Just4pLeisure | 0:e0b964252a05 | 225 | // Trionic5GetAdaptionData |
Just4pLeisure | 0:e0b964252a05 | 226 | // |
Just4pLeisure | 0:e0b964252a05 | 227 | // Gets the adaption data from the T5's SRAM. |
Just4pLeisure | 0:e0b964252a05 | 228 | // The adaption data is stored in a hex file, adaption.hex, on the mbed 'local' file system 'disk'. |
Just4pLeisure | 0:e0b964252a05 | 229 | // |
Just4pLeisure | 0:e0b964252a05 | 230 | // Reading the Adaption data from SRAM takes about 16 seconds. |
Just4pLeisure | 0:e0b964252a05 | 231 | // |
Just4pLeisure | 0:e0b964252a05 | 232 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 233 | // return: bool TRUE if all went OK, FALSE if there was an error. |
Just4pLeisure | 0:e0b964252a05 | 234 | // |
Just4pLeisure | 0:e0b964252a05 | 235 | bool Trionic5GetAdaptionData() { |
Just4pLeisure | 0:e0b964252a05 | 236 | printf("getting adaption data\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 237 | FILE *fp = fopen("/local/adaption.hex", "w"); // Open "adaption.hex" on the local file system for writing |
Just4pLeisure | 0:e0b964252a05 | 238 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 239 | printf("opened adaption data file\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 240 | unsigned int address = 5; // Mysterious reason for starting at 5 !!! |
Just4pLeisure | 0:e0b964252a05 | 241 | char RAMdata[6]; |
Just4pLeisure | 0:e0b964252a05 | 242 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 243 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 244 | for (int i=0; i<5462; i++) { // Mysterious number 5462 is 0x8000 / 6 - rounded up !!! |
Just4pLeisure | 0:e0b964252a05 | 245 | T5ReadRAM(RAMdata, address); |
Just4pLeisure | 0:e0b964252a05 | 246 | address += 6; |
Just4pLeisure | 0:e0b964252a05 | 247 | for (int j=0; j<6; j++) { |
Just4pLeisure | 0:e0b964252a05 | 248 | if (((i*6) + j) < T5RAMSIZE) |
Just4pLeisure | 0:e0b964252a05 | 249 | fputc(RAMdata[j],fp); |
Just4pLeisure | 0:e0b964252a05 | 250 | } |
Just4pLeisure | 0:e0b964252a05 | 251 | } |
Just4pLeisure | 0:e0b964252a05 | 252 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 253 | printf("Getting the RAM Data took %f seconds.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 254 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 255 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 256 | } |
Just4pLeisure | 0:e0b964252a05 | 257 | |
Just4pLeisure | 0:e0b964252a05 | 258 | // |
Just4pLeisure | 0:e0b964252a05 | 259 | // Trionic5SendBootLoader |
Just4pLeisure | 0:e0b964252a05 | 260 | // |
Just4pLeisure | 0:e0b964252a05 | 261 | // Sends a 'bootloader' file, booty.s19 to the T5 ECU. |
Just4pLeisure | 0:e0b964252a05 | 262 | // The 'bootloader' is stored on the mbed 'local' file system 'disk' and must be in S19 format. |
Just4pLeisure | 0:e0b964252a05 | 263 | // |
Just4pLeisure | 0:e0b964252a05 | 264 | // The 'bootloader' is then able to dump or reFLASH the T5 ECU FLASH chips - this is the whole point of the exercise :-) |
Just4pLeisure | 0:e0b964252a05 | 265 | // |
Just4pLeisure | 0:e0b964252a05 | 266 | // Sending the 'bootloader' to the T5 ECU takes just over 1 second. |
Just4pLeisure | 0:e0b964252a05 | 267 | // |
Just4pLeisure | 0:e0b964252a05 | 268 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 269 | // return: bool TRUE if all went OK, |
Just4pLeisure | 0:e0b964252a05 | 270 | // FALSE if the 'bootloader' wasn't sent for some reason. |
Just4pLeisure | 0:e0b964252a05 | 271 | // |
Just4pLeisure | 0:e0b964252a05 | 272 | bool Trionic5SendBootLoader() { |
Just4pLeisure | 0:e0b964252a05 | 273 | FILE *fp = fopen("/local/MyBooty.S19", "r"); // Open "booty.s19" on the local file system for reading |
Just4pLeisure | 0:e0b964252a05 | 274 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 275 | int c = 0; // for some reason fgetc returns an int instead of a char |
Just4pLeisure | 0:e0b964252a05 | 276 | int count = 0; // count of bytes in the S-record can be 0xFF = 255 in decimal |
Just4pLeisure | 0:e0b964252a05 | 277 | int asize = 0; // 2,3 or 4 bytes in address |
Just4pLeisure | 0:e0b964252a05 | 278 | unsigned int address = 0; // address to put S-record |
Just4pLeisure | 0:e0b964252a05 | 279 | int checksum = 0; // checksum check at the end of each S-record line |
Just4pLeisure | 0:e0b964252a05 | 280 | char msg[8]; // Construct the bootloader frame for uploading |
Just4pLeisure | 0:e0b964252a05 | 281 | bool sent = FALSE; |
Just4pLeisure | 0:e0b964252a05 | 282 | |
Just4pLeisure | 0:e0b964252a05 | 283 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 284 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 285 | while (!sent) { |
Just4pLeisure | 0:e0b964252a05 | 286 | |
Just4pLeisure | 0:e0b964252a05 | 287 | do c = fgetc (fp); // get characters until we get an 'S' (throws away \n,\r characters and other junk) |
Just4pLeisure | 0:e0b964252a05 | 288 | while (c != 'S' && c != EOF); |
Just4pLeisure | 0:e0b964252a05 | 289 | // if (c == EOF) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 290 | c = fgetc(fp); // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) |
Just4pLeisure | 0:e0b964252a05 | 291 | // if ((c = fgetc(fp)) == EOF) return '\a'; // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) |
Just4pLeisure | 0:e0b964252a05 | 292 | switch (c) { |
Just4pLeisure | 0:e0b964252a05 | 293 | case '0': |
Just4pLeisure | 0:e0b964252a05 | 294 | break; // Skip over S0 header record |
Just4pLeisure | 0:e0b964252a05 | 295 | |
Just4pLeisure | 0:e0b964252a05 | 296 | case '1': |
Just4pLeisure | 0:e0b964252a05 | 297 | case '2': |
Just4pLeisure | 0:e0b964252a05 | 298 | case '3': |
Just4pLeisure | 0:e0b964252a05 | 299 | asize = 1 + c - '0'; // 2, 3 or 4 bytes for address |
Just4pLeisure | 0:e0b964252a05 | 300 | address = 0; |
Just4pLeisure | 0:e0b964252a05 | 301 | // get the number of bytes (in ascii format) in this S-record line |
Just4pLeisure | 0:e0b964252a05 | 302 | // there must be at least the address and the checksum so return with an error if less than this! |
Just4pLeisure | 0:e0b964252a05 | 303 | if ((c = SRecGetByte(fp)) < (asize + 1)) break; |
Just4pLeisure | 0:e0b964252a05 | 304 | // if ((c = SRecGetByte(fp)) < 3) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 305 | count = c; |
Just4pLeisure | 0:e0b964252a05 | 306 | checksum = c; |
Just4pLeisure | 0:e0b964252a05 | 307 | // get the address |
Just4pLeisure | 0:e0b964252a05 | 308 | for (int i=0; i<asize; i++) { |
Just4pLeisure | 0:e0b964252a05 | 309 | c = SRecGetByte(fp); |
Just4pLeisure | 0:e0b964252a05 | 310 | checksum += c; |
Just4pLeisure | 0:e0b964252a05 | 311 | address <<= 8; |
Just4pLeisure | 0:e0b964252a05 | 312 | address |= c; |
Just4pLeisure | 0:e0b964252a05 | 313 | count--; |
Just4pLeisure | 0:e0b964252a05 | 314 | } |
Just4pLeisure | 0:e0b964252a05 | 315 | // send a bootloader address message |
Just4pLeisure | 0:e0b964252a05 | 316 | T5SendBootAddress(address, (count-1)); |
Just4pLeisure | 0:e0b964252a05 | 317 | // T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 318 | T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 319 | // get and send the bootloader frames for this S-record |
Just4pLeisure | 0:e0b964252a05 | 320 | // NOTE the last frame sent may have less than 7 real data bytes but 7 bytes are always sent. In this case the unnecessary bytes |
Just4pLeisure | 0:e0b964252a05 | 321 | // are repeated from the previous frame. This is OK because the T5 ECU knows how many bytes to expect (because the count of bytes |
Just4pLeisure | 0:e0b964252a05 | 322 | // in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame. |
Just4pLeisure | 0:e0b964252a05 | 323 | for (int i=0; i<count-1; i++) { |
Just4pLeisure | 0:e0b964252a05 | 324 | c = SRecGetByte(fp); |
Just4pLeisure | 0:e0b964252a05 | 325 | checksum += c; |
Just4pLeisure | 0:e0b964252a05 | 326 | msg[1+(i%7)] = c; |
Just4pLeisure | 0:e0b964252a05 | 327 | if (i%7 == 0) msg[0]=i; // set the index number |
Just4pLeisure | 0:e0b964252a05 | 328 | if ((i%7 == 6) || (i == count - 2)) { |
Just4pLeisure | 0:e0b964252a05 | 329 | T5SendBootFrame(msg); |
Just4pLeisure | 0:e0b964252a05 | 330 | // T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 331 | T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 332 | } |
Just4pLeisure | 0:e0b964252a05 | 333 | } |
Just4pLeisure | 0:e0b964252a05 | 334 | // get the checksum |
Just4pLeisure | 0:e0b964252a05 | 335 | if (((checksum += SRecGetByte(fp)) | 0xFF) != 0xFF) break; |
Just4pLeisure | 0:e0b964252a05 | 336 | // if ((checksum += SRecGetByte(fp)) != 0xff) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 337 | break; |
Just4pLeisure | 0:e0b964252a05 | 338 | |
Just4pLeisure | 0:e0b964252a05 | 339 | case '5': |
Just4pLeisure | 0:e0b964252a05 | 340 | break; // Skip over S5 record types |
Just4pLeisure | 0:e0b964252a05 | 341 | |
Just4pLeisure | 0:e0b964252a05 | 342 | case '7': |
Just4pLeisure | 0:e0b964252a05 | 343 | case '8': |
Just4pLeisure | 0:e0b964252a05 | 344 | case '9': |
Just4pLeisure | 0:e0b964252a05 | 345 | asize = 11 - (c - '0'); // 2, 3 or 4 bytes for address |
Just4pLeisure | 0:e0b964252a05 | 346 | // get the number of bytes (in ascii format) in this S-record line there must be just the address and the checksum |
Just4pLeisure | 0:e0b964252a05 | 347 | // so return with an error if other than this! |
Just4pLeisure | 0:e0b964252a05 | 348 | printf("Starting the bootloader, "); |
Just4pLeisure | 0:e0b964252a05 | 349 | if ((c = SRecGetByte(fp)) != (asize + 1)) break; |
Just4pLeisure | 0:e0b964252a05 | 350 | // if ((c = SRecGetByte(fp)) < 3) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 351 | printf("so far so good"); |
Just4pLeisure | 0:e0b964252a05 | 352 | checksum = c; |
Just4pLeisure | 0:e0b964252a05 | 353 | // get the address |
Just4pLeisure | 0:e0b964252a05 | 354 | for (int i=0; i<asize; i++) { |
Just4pLeisure | 0:e0b964252a05 | 355 | c = SRecGetByte(fp); |
Just4pLeisure | 0:e0b964252a05 | 356 | checksum += c; |
Just4pLeisure | 0:e0b964252a05 | 357 | address <<= 8; |
Just4pLeisure | 0:e0b964252a05 | 358 | address |= c; |
Just4pLeisure | 0:e0b964252a05 | 359 | } |
Just4pLeisure | 0:e0b964252a05 | 360 | printf("calculated the address, "); |
Just4pLeisure | 0:e0b964252a05 | 361 | // get the checksum |
Just4pLeisure | 0:e0b964252a05 | 362 | // if (((checksum += SRecGetByte(fp)) | 0xFF) != 0xFF) break; |
Just4pLeisure | 0:e0b964252a05 | 363 | // if ((checksum += SRecGetByte(fp)) != 0xff) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 364 | printf("checksum is OK, "); |
Just4pLeisure | 0:e0b964252a05 | 365 | T5StartBootLoader(address); |
Just4pLeisure | 0:e0b964252a05 | 366 | // T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 367 | sent = TRUE; |
Just4pLeisure | 0:e0b964252a05 | 368 | printf("and we're done :-) \r\n"); |
Just4pLeisure | 0:e0b964252a05 | 369 | break; |
Just4pLeisure | 0:e0b964252a05 | 370 | |
Just4pLeisure | 0:e0b964252a05 | 371 | // Some kind of invalid S-record type so break |
Just4pLeisure | 0:e0b964252a05 | 372 | default: |
Just4pLeisure | 0:e0b964252a05 | 373 | printf("oops - didn't recognise that S-Record \r\n"); |
Just4pLeisure | 0:e0b964252a05 | 374 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 375 | // return SREC_FORMAT; |
Just4pLeisure | 0:e0b964252a05 | 376 | } |
Just4pLeisure | 0:e0b964252a05 | 377 | } |
Just4pLeisure | 0:e0b964252a05 | 378 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 379 | printf("Uploading and starting the bootloader took %f seconds. \r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 380 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 381 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 382 | } |
Just4pLeisure | 0:e0b964252a05 | 383 | |
Just4pLeisure | 0:e0b964252a05 | 384 | // |
Just4pLeisure | 0:e0b964252a05 | 385 | // Trionic5GetChecksum |
Just4pLeisure | 0:e0b964252a05 | 386 | // |
Just4pLeisure | 0:e0b964252a05 | 387 | // Calculates the checksum of the FLASH in the T5 ECU. |
Just4pLeisure | 0:e0b964252a05 | 388 | // The 'bootloader', booty.s19, must be loaded before this function can be used. |
Just4pLeisure | 0:e0b964252a05 | 389 | // The 'bootloader' actually calculates the checksum and compares it with the |
Just4pLeisure | 0:e0b964252a05 | 390 | // value stored in the 'header' region at the end of the FLASH. |
Just4pLeisure | 0:e0b964252a05 | 391 | // |
Just4pLeisure | 0:e0b964252a05 | 392 | // The bootloader sends a single CAN message with the result e.g. |
Just4pLeisure | 0:e0b964252a05 | 393 | // w00C8C800CAFEBABE0808 |
Just4pLeisure | 0:e0b964252a05 | 394 | // 00C - T5 response messages have an CAN id of 00C |
Just4pLeisure | 0:e0b964252a05 | 395 | // 8 - All T5 messages have a message length of 8 bytes |
Just4pLeisure | 0:e0b964252a05 | 396 | // C8 - This is the checksum message type |
Just4pLeisure | 0:e0b964252a05 | 397 | // 00 - 00 means OK, the checksum calculation matches the stored value which in this case is: |
Just4pLeisure | 0:e0b964252a05 | 398 | // CAFEBABE - lol :-) |
Just4pLeisure | 0:e0b964252a05 | 399 | // |
Just4pLeisure | 0:e0b964252a05 | 400 | // w00C8C801FFFFFFFF0808 |
Just4pLeisure | 0:e0b964252a05 | 401 | // 01 - 01 means calculated value doesn't matched the stored value |
Just4pLeisure | 0:e0b964252a05 | 402 | // FFFFFFFF - in this case the stored value is FFFFFFFF - the chips might be erased |
Just4pLeisure | 0:e0b964252a05 | 403 | // |
Just4pLeisure | 0:e0b964252a05 | 404 | // Calculating the checksum takes a little under 2 seconds. |
Just4pLeisure | 0:e0b964252a05 | 405 | // |
Just4pLeisure | 0:e0b964252a05 | 406 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 407 | // return: bool TRUE if all went OK, |
Just4pLeisure | 0:e0b964252a05 | 408 | // |
Just4pLeisure | 0:e0b964252a05 | 409 | bool Trionic5GetChecksum() { |
Just4pLeisure | 0:e0b964252a05 | 410 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 411 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 412 | T5BootCSumCmnd(); |
Just4pLeisure | 0:e0b964252a05 | 413 | T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 414 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 415 | printf("T5 ECU took took %f seconds to calculate it's checksum.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 416 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 417 | } |
Just4pLeisure | 0:e0b964252a05 | 418 | |
Just4pLeisure | 0:e0b964252a05 | 419 | // |
Just4pLeisure | 0:e0b964252a05 | 420 | // Trionic5BootloaderReset |
Just4pLeisure | 0:e0b964252a05 | 421 | // |
Just4pLeisure | 0:e0b964252a05 | 422 | // Exits the Bootloader and restart the T5 ECU |
Just4pLeisure | 0:e0b964252a05 | 423 | // |
Just4pLeisure | 0:e0b964252a05 | 424 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 425 | // outputs: bool TRUE if all went OK. |
Just4pLeisure | 0:e0b964252a05 | 426 | // |
Just4pLeisure | 0:e0b964252a05 | 427 | bool Trionic5BootloaderReset() { |
Just4pLeisure | 0:e0b964252a05 | 428 | T5BootResetCmnd(); |
Just4pLeisure | 0:e0b964252a05 | 429 | T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 430 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 431 | } |
Just4pLeisure | 0:e0b964252a05 | 432 | |
Just4pLeisure | 0:e0b964252a05 | 433 | // |
Just4pLeisure | 0:e0b964252a05 | 434 | // Trionic5GetChipTypes |
Just4pLeisure | 0:e0b964252a05 | 435 | // |
Just4pLeisure | 0:e0b964252a05 | 436 | // Gets the FLASH chip type fitted. |
Just4pLeisure | 0:e0b964252a05 | 437 | // |
Just4pLeisure | 0:e0b964252a05 | 438 | // NOTE the bootloader must be loaded in order to use this function. |
Just4pLeisure | 0:e0b964252a05 | 439 | // |
Just4pLeisure | 0:e0b964252a05 | 440 | // CAN messages from the T5 ECU with FLASH data look like this: |
Just4pLeisure | 0:e0b964252a05 | 441 | // |
Just4pLeisure | 0:e0b964252a05 | 442 | // C9,00,aa,aa,aa,aa,mm,dd, |
Just4pLeisure | 0:e0b964252a05 | 443 | // |
Just4pLeisure | 0:e0b964252a05 | 444 | // C9 lets us know its a FLASH id message |
Just4pLeisure | 0:e0b964252a05 | 445 | // |
Just4pLeisure | 0:e0b964252a05 | 446 | // aa,aa,aa,aa is the FLASH start address which we can use to work out if this is a T5.2 or T5.5 ECU |
Just4pLeisure | 0:e0b964252a05 | 447 | // 0x00020000 - T5.2 |
Just4pLeisure | 0:e0b964252a05 | 448 | // 0x00040000 - T5.5 |
Just4pLeisure | 0:e0b964252a05 | 449 | // |
Just4pLeisure | 0:e0b964252a05 | 450 | // mm = Manufacturer id. These can be: |
Just4pLeisure | 0:e0b964252a05 | 451 | // 0x89 - Intel |
Just4pLeisure | 0:e0b964252a05 | 452 | // 0x31 - CSI/CAT |
Just4pLeisure | 0:e0b964252a05 | 453 | // 0x01 - AMD |
Just4pLeisure | 0:e0b964252a05 | 454 | // 0x1F - Atmel |
Just4pLeisure | 0:e0b964252a05 | 455 | // |
Just4pLeisure | 0:e0b964252a05 | 456 | // dd = Device id. These can be: |
Just4pLeisure | 0:e0b964252a05 | 457 | // 0xB8 - Intel _or_ CSI 28F512 (Fiited by Saab in T5.2) |
Just4pLeisure | 0:e0b964252a05 | 458 | // 0xB4 - Intel _or_ CSI 28F010 (Fitted by Saab in T5.5) |
Just4pLeisure | 0:e0b964252a05 | 459 | // 0x25 - AMD 28F512 (Fiited by Saab in T5.2) |
Just4pLeisure | 0:e0b964252a05 | 460 | // 0xA7 - AMD 28F010 (Fitted by Saab in T5.5) |
Just4pLeisure | 0:e0b964252a05 | 461 | // 0x20 - AMD 29F010 (Some people have put these in their T5.5) |
Just4pLeisure | 0:e0b964252a05 | 462 | // 0x5D - Atmel 29C512 (Some people mave have put these in their T5.2) |
Just4pLeisure | 0:e0b964252a05 | 463 | // 0xD5 - Atmel 29C010 (Some people have put these in their T5.5) |
Just4pLeisure | 0:e0b964252a05 | 464 | // |
Just4pLeisure | 0:e0b964252a05 | 465 | // mm = 0xFF, dd == 0xF7 probably means that the programming voltage isn't right. |
Just4pLeisure | 0:e0b964252a05 | 466 | // |
Just4pLeisure | 0:e0b964252a05 | 467 | // Finding out which ECU type and FLASH chips are fitted takes under a second. |
Just4pLeisure | 0:e0b964252a05 | 468 | // |
Just4pLeisure | 0:e0b964252a05 | 469 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 470 | // return: bool TRUE if all went OK. |
Just4pLeisure | 0:e0b964252a05 | 471 | // |
Just4pLeisure | 0:e0b964252a05 | 472 | bool Trionic5GetChipTypes() { |
Just4pLeisure | 0:e0b964252a05 | 473 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 474 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 475 | T5BootFLASHType(); |
Just4pLeisure | 0:e0b964252a05 | 476 | T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 477 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 478 | printf("Getting the FLASH chip id took %f seconds.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 479 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 480 | } |
Just4pLeisure | 0:e0b964252a05 | 481 | |
Just4pLeisure | 0:e0b964252a05 | 482 | // |
Just4pLeisure | 0:e0b964252a05 | 483 | // Trionic5EraseFLASH |
Just4pLeisure | 0:e0b964252a05 | 484 | // |
Just4pLeisure | 0:e0b964252a05 | 485 | // Erases the FLASH Chips. |
Just4pLeisure | 0:e0b964252a05 | 486 | // |
Just4pLeisure | 0:e0b964252a05 | 487 | // NOTE the bootloader must be loaded in order to use this function. |
Just4pLeisure | 0:e0b964252a05 | 488 | // |
Just4pLeisure | 0:e0b964252a05 | 489 | // CAN messages from the T5 ECU with FLASH erase command look like this: |
Just4pLeisure | 0:e0b964252a05 | 490 | // |
Just4pLeisure | 0:e0b964252a05 | 491 | // C0,cc,08,08,08,08,08,08 |
Just4pLeisure | 0:e0b964252a05 | 492 | // |
Just4pLeisure | 0:e0b964252a05 | 493 | // C0 tells us this is a response to the FLASH erase command. |
Just4pLeisure | 0:e0b964252a05 | 494 | // |
Just4pLeisure | 0:e0b964252a05 | 495 | // cc is a code that tells us what happened: |
Just4pLeisure | 0:e0b964252a05 | 496 | // 00 - FLASH was erased OK |
Just4pLeisure | 0:e0b964252a05 | 497 | // 01 - Could not erase FLASH chips to 0xFF |
Just4pLeisure | 0:e0b964252a05 | 498 | // 02 - Could not write 0x00 to 28F FLASH chips |
Just4pLeisure | 0:e0b964252a05 | 499 | // 03 - Unrecognised FLASH chip type (or maybe programming voltage isn't right) |
Just4pLeisure | 0:e0b964252a05 | 500 | // 04 - Intel chips found, but unrecognised type |
Just4pLeisure | 0:e0b964252a05 | 501 | // 05 - AMD chips found, but unrecognised type |
Just4pLeisure | 0:e0b964252a05 | 502 | // 06 - CSI/Catalyst chips found, but unrecognised type |
Just4pLeisure | 0:e0b964252a05 | 503 | // 07 - Atmel chips found - Atmel chips don't need to be erased |
Just4pLeisure | 0:e0b964252a05 | 504 | // |
Just4pLeisure | 0:e0b964252a05 | 505 | // Erasing 28F type FLASH chips takes around 22 seconds. 29F chips should be erased much more quickly. |
Just4pLeisure | 0:e0b964252a05 | 506 | // |
Just4pLeisure | 0:e0b964252a05 | 507 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 508 | // return: bool TRUE if all went OK. |
Just4pLeisure | 0:e0b964252a05 | 509 | // |
Just4pLeisure | 0:e0b964252a05 | 510 | bool Trionic5EraseFLASH() { |
Just4pLeisure | 0:e0b964252a05 | 511 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 512 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 513 | T5BootEraseCmnd(); |
Just4pLeisure | 0:e0b964252a05 | 514 | T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 515 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 516 | printf("Erasing the FLASH took %f seconds.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 517 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 518 | } |
Just4pLeisure | 0:e0b964252a05 | 519 | |
Just4pLeisure | 0:e0b964252a05 | 520 | // |
Just4pLeisure | 0:e0b964252a05 | 521 | // Trionic5DumpFLASH |
Just4pLeisure | 0:e0b964252a05 | 522 | // |
Just4pLeisure | 0:e0b964252a05 | 523 | // Dumps the FLASH chip BIN file, original.hex to the mbed 'disk' |
Just4pLeisure | 0:e0b964252a05 | 524 | // |
Just4pLeisure | 0:e0b964252a05 | 525 | // NOTE the bootloader must be loaded in order to use this function. |
Just4pLeisure | 0:e0b964252a05 | 526 | // |
Just4pLeisure | 0:e0b964252a05 | 527 | // CAN messages from the T5 ECU with FLASH data look like this: |
Just4pLeisure | 0:e0b964252a05 | 528 | // |
Just4pLeisure | 0:e0b964252a05 | 529 | // A6,mm,dd,dd,dd,dd,08,08 |
Just4pLeisure | 0:e0b964252a05 | 530 | // |
Just4pLeisure | 0:e0b964252a05 | 531 | // A6 lets us know its a FLASH data message |
Just4pLeisure | 0:e0b964252a05 | 532 | // mm tells us if there is any more data |
Just4pLeisure | 0:e0b964252a05 | 533 | // mm == 04 means at least 4 more bytes to come |
Just4pLeisure | 0:e0b964252a05 | 534 | // mm == 00 means that these are the last FLASH data bytes |
Just4pLeisure | 0:e0b964252a05 | 535 | // dd,dd,dd,dd are 4 FLASH data bytes |
Just4pLeisure | 0:e0b964252a05 | 536 | // The last 2 bytes are 08,08 they aren't and don't meean anything |
Just4pLeisure | 0:e0b964252a05 | 537 | // (It would be more efficient to dump 6 bytes at a time because less |
Just4pLeisure | 0:e0b964252a05 | 538 | // CAN messages would be needed but it was easier to write the |
Just4pLeisure | 0:e0b964252a05 | 539 | // bootloader to send just 4 bytes so that's what I did) |
Just4pLeisure | 0:e0b964252a05 | 540 | // |
Just4pLeisure | 0:e0b964252a05 | 541 | // Dumping FLASH chips in a T5.5 ECU takes around 88 seconds. Dumping T5.2 ECUs should take about half of this time |
Just4pLeisure | 0:e0b964252a05 | 542 | // |
Just4pLeisure | 0:e0b964252a05 | 543 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 544 | // return: bool TRUE if all went OK. |
Just4pLeisure | 0:e0b964252a05 | 545 | // |
Just4pLeisure | 0:e0b964252a05 | 546 | bool Trionic5DumpFLASH() { |
Just4pLeisure | 0:e0b964252a05 | 547 | printf("getting FLASH BIN file\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 548 | FILE *fp = fopen("/local/original.hex", "w"); // Open "original.hex" on the local file system for writing |
Just4pLeisure | 0:e0b964252a05 | 549 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 550 | printf("opened FLASH BIN file\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 551 | char FLASHdata[8]; |
Just4pLeisure | 0:e0b964252a05 | 552 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 553 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 554 | // int count = 0; |
Just4pLeisure | 0:e0b964252a05 | 555 | do { |
Just4pLeisure | 0:e0b964252a05 | 556 | T5BootDumpFLASHCmnd(); |
Just4pLeisure | 0:e0b964252a05 | 557 | // T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 558 | T5WaitFLASH(FLASHdata); |
Just4pLeisure | 0:e0b964252a05 | 559 | for (int j=0; j<4; j++) { |
Just4pLeisure | 0:e0b964252a05 | 560 | fputc(FLASHdata[j+2],fp); |
Just4pLeisure | 0:e0b964252a05 | 561 | // count++; |
Just4pLeisure | 0:e0b964252a05 | 562 | } |
Just4pLeisure | 0:e0b964252a05 | 563 | } while (FLASHdata[1] != 0); |
Just4pLeisure | 0:e0b964252a05 | 564 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 565 | // printf("count = 0x%x\r\n", count); |
Just4pLeisure | 0:e0b964252a05 | 566 | printf("Getting the FLASH BIN took %f seconds.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 567 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 568 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 569 | } |
Just4pLeisure | 0:e0b964252a05 | 570 | |
Just4pLeisure | 0:e0b964252a05 | 571 | |
Just4pLeisure | 0:e0b964252a05 | 572 | // |
Just4pLeisure | 0:e0b964252a05 | 573 | // Trionic5DumpFLASH2 |
Just4pLeisure | 0:e0b964252a05 | 574 | // |
Just4pLeisure | 0:e0b964252a05 | 575 | // Gets the adaption data from the T5's SRAM. |
Just4pLeisure | 0:e0b964252a05 | 576 | // The adaption data is stored in a hex file, adaption.hex, on the mbed 'local' file system 'disk'. |
Just4pLeisure | 0:e0b964252a05 | 577 | // |
Just4pLeisure | 0:e0b964252a05 | 578 | // Reading the Adaption data from SRAM takes about 16 seconds. |
Just4pLeisure | 0:e0b964252a05 | 579 | // |
Just4pLeisure | 0:e0b964252a05 | 580 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 581 | // return: bool TRUE if all went OK, FALSE if there was an error. |
Just4pLeisure | 0:e0b964252a05 | 582 | // |
Just4pLeisure | 0:e0b964252a05 | 583 | bool Trionic5DumpFLASH2() { |
Just4pLeisure | 0:e0b964252a05 | 584 | printf("getting FLASH BIN file\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 585 | FILE *fp = fopen("/local/original.hex", "w"); // Open "adaption.hex" on the local file system for writing |
Just4pLeisure | 0:e0b964252a05 | 586 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 587 | printf("opened FLASH BIN file\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 588 | unsigned int address = 0x40005; // Mysterious reason for starting at 5 !!! |
Just4pLeisure | 0:e0b964252a05 | 589 | char FLASHdata[6]; |
Just4pLeisure | 0:e0b964252a05 | 590 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 591 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 592 | for (int i=0; i<43690; i++) { // Mysterious number 43690 is 0x40000 / 6 |
Just4pLeisure | 0:e0b964252a05 | 593 | T5ReadFLASH(FLASHdata, address); |
Just4pLeisure | 0:e0b964252a05 | 594 | address += 6; |
Just4pLeisure | 0:e0b964252a05 | 595 | for (int j=0; j<6; j++) { |
Just4pLeisure | 0:e0b964252a05 | 596 | fputc(FLASHdata[j],fp); |
Just4pLeisure | 0:e0b964252a05 | 597 | } |
Just4pLeisure | 0:e0b964252a05 | 598 | } |
Just4pLeisure | 0:e0b964252a05 | 599 | address = 0x7FFFF; |
Just4pLeisure | 0:e0b964252a05 | 600 | T5ReadFLASH(FLASHdata, address); |
Just4pLeisure | 0:e0b964252a05 | 601 | for (int j=0; j<4; j++) { |
Just4pLeisure | 0:e0b964252a05 | 602 | fputc(FLASHdata[j+2],fp); |
Just4pLeisure | 0:e0b964252a05 | 603 | } |
Just4pLeisure | 0:e0b964252a05 | 604 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 605 | printf("Getting the FLASH BIN took %f seconds.\r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 606 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 607 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 608 | } |
Just4pLeisure | 0:e0b964252a05 | 609 | |
Just4pLeisure | 0:e0b964252a05 | 610 | // |
Just4pLeisure | 0:e0b964252a05 | 611 | // Trionic5SendFLASHUpdate |
Just4pLeisure | 0:e0b964252a05 | 612 | // |
Just4pLeisure | 0:e0b964252a05 | 613 | // Sends a FLASH update file, modified.s19 to the T5 ECU. |
Just4pLeisure | 0:e0b964252a05 | 614 | // The FLASH update file is stored on the local file system and must be in S19 format. |
Just4pLeisure | 0:e0b964252a05 | 615 | // |
Just4pLeisure | 0:e0b964252a05 | 616 | // FLASHing a T5.5 ECU takes around 90 seconds. FLASHing T5.2 ECUs should take about half of this time |
Just4pLeisure | 0:e0b964252a05 | 617 | // |
Just4pLeisure | 0:e0b964252a05 | 618 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 619 | // return: bool TRUE if all went OK, |
Just4pLeisure | 0:e0b964252a05 | 620 | // FALSE if the FLASH update failed for some reason. |
Just4pLeisure | 0:e0b964252a05 | 621 | // |
Just4pLeisure | 0:e0b964252a05 | 622 | bool Trionic5SendFLASHUpdate() { |
Just4pLeisure | 0:e0b964252a05 | 623 | FILE *fp = fopen("/local/modified.s19", "r"); // Open "modified.s19" on the local file system for reading |
Just4pLeisure | 0:e0b964252a05 | 624 | if (!fp) return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 625 | printf("Opened MODIFIED.S19 "); |
Just4pLeisure | 0:e0b964252a05 | 626 | int c = 0; // for some reason fgetc returns an int instead of a char |
Just4pLeisure | 0:e0b964252a05 | 627 | int count = 0; // count of bytes in the S-record can be 0xFF = 255 in decimal |
Just4pLeisure | 0:e0b964252a05 | 628 | int asize = 0; // 2,3 or 4 bytes in address |
Just4pLeisure | 0:e0b964252a05 | 629 | unsigned int address = 0; // address to put S-record |
Just4pLeisure | 0:e0b964252a05 | 630 | int checksum = 0; // checksum check at the end |
Just4pLeisure | 0:e0b964252a05 | 631 | char msg[8]; // Construct the bootloader frame for uploading |
Just4pLeisure | 0:e0b964252a05 | 632 | bool sent = FALSE; |
Just4pLeisure | 0:e0b964252a05 | 633 | |
Just4pLeisure | 0:e0b964252a05 | 634 | timer.reset(); |
Just4pLeisure | 0:e0b964252a05 | 635 | timer.start(); |
Just4pLeisure | 0:e0b964252a05 | 636 | while (!sent) { |
Just4pLeisure | 0:e0b964252a05 | 637 | |
Just4pLeisure | 0:e0b964252a05 | 638 | do c = fgetc (fp); // get characters until we get an 'S' (throws away \n,\r characters and other junk) |
Just4pLeisure | 0:e0b964252a05 | 639 | while (c != 'S' && c != EOF); |
Just4pLeisure | 0:e0b964252a05 | 640 | // if (c == EOF) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 641 | c = fgetc(fp); // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) |
Just4pLeisure | 0:e0b964252a05 | 642 | // if ((c = fgetc(fp)) == EOF) return '\a'; // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) |
Just4pLeisure | 0:e0b964252a05 | 643 | switch (c) { |
Just4pLeisure | 0:e0b964252a05 | 644 | case '0': |
Just4pLeisure | 0:e0b964252a05 | 645 | break; // Skip over S0 header record |
Just4pLeisure | 0:e0b964252a05 | 646 | |
Just4pLeisure | 0:e0b964252a05 | 647 | case '1': |
Just4pLeisure | 0:e0b964252a05 | 648 | case '2': |
Just4pLeisure | 0:e0b964252a05 | 649 | case '3': |
Just4pLeisure | 0:e0b964252a05 | 650 | asize = 1 + c - '0'; // 2, 3 or 4 bytes for address |
Just4pLeisure | 0:e0b964252a05 | 651 | address = 0; |
Just4pLeisure | 0:e0b964252a05 | 652 | // get the number of bytes (in ascii format) in this S-record line |
Just4pLeisure | 0:e0b964252a05 | 653 | // there must be at least the address and the checksum so return with an error if less than this! |
Just4pLeisure | 0:e0b964252a05 | 654 | if ((c = SRecGetByte(fp)) < (asize + 1)) break; |
Just4pLeisure | 0:e0b964252a05 | 655 | // if ((c = SRecGetByte(fp)) < 3) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 656 | count = c; |
Just4pLeisure | 0:e0b964252a05 | 657 | checksum = c; |
Just4pLeisure | 0:e0b964252a05 | 658 | // get the address |
Just4pLeisure | 0:e0b964252a05 | 659 | for (int i=0; i<asize; i++) { |
Just4pLeisure | 0:e0b964252a05 | 660 | c = SRecGetByte(fp); |
Just4pLeisure | 0:e0b964252a05 | 661 | checksum += c; |
Just4pLeisure | 0:e0b964252a05 | 662 | address <<= 8; |
Just4pLeisure | 0:e0b964252a05 | 663 | address |= c; |
Just4pLeisure | 0:e0b964252a05 | 664 | count--; |
Just4pLeisure | 0:e0b964252a05 | 665 | } |
Just4pLeisure | 0:e0b964252a05 | 666 | address += 0x40000; // Only for T5.5 at the moment !!! |
Just4pLeisure | 0:e0b964252a05 | 667 | // send a bootloader address message |
Just4pLeisure | 0:e0b964252a05 | 668 | T5SendBootAddress(address, (count-1)); |
Just4pLeisure | 0:e0b964252a05 | 669 | // T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 670 | T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 671 | // get and send the bootloader frames for this S-record |
Just4pLeisure | 0:e0b964252a05 | 672 | // NOTE the last frame sent may have less than 7 real data bytes but 7 bytes are always sent. In this case the unnecessary bytes |
Just4pLeisure | 0:e0b964252a05 | 673 | // are repeated from the previous frame. This is OK because the T5 ECU knows how many bytes to expect (because the count of bytes |
Just4pLeisure | 0:e0b964252a05 | 674 | // in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame. |
Just4pLeisure | 0:e0b964252a05 | 675 | for (int i=0; i<count-1; i++) { |
Just4pLeisure | 0:e0b964252a05 | 676 | c = SRecGetByte(fp); |
Just4pLeisure | 0:e0b964252a05 | 677 | checksum += c; |
Just4pLeisure | 0:e0b964252a05 | 678 | msg[1+(i%7)] = c; |
Just4pLeisure | 0:e0b964252a05 | 679 | if (i%7 == 0) msg[0]=i; // set the index number |
Just4pLeisure | 0:e0b964252a05 | 680 | if ((i%7 == 6) || (i == count - 2)) { |
Just4pLeisure | 0:e0b964252a05 | 681 | T5SendBootFrame(msg); |
Just4pLeisure | 0:e0b964252a05 | 682 | // T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 683 | T5WaitResponse(); |
Just4pLeisure | 0:e0b964252a05 | 684 | } |
Just4pLeisure | 0:e0b964252a05 | 685 | } |
Just4pLeisure | 0:e0b964252a05 | 686 | // get the checksum |
Just4pLeisure | 0:e0b964252a05 | 687 | if (((checksum += SRecGetByte(fp)) | 0xFF) != 0xFF) break; |
Just4pLeisure | 0:e0b964252a05 | 688 | // if ((checksum += SRecGetByte(fp)) != 0xff) return '\a'; |
Just4pLeisure | 0:e0b964252a05 | 689 | break; |
Just4pLeisure | 0:e0b964252a05 | 690 | |
Just4pLeisure | 0:e0b964252a05 | 691 | case '5': |
Just4pLeisure | 0:e0b964252a05 | 692 | break; // Skip over S5 record types |
Just4pLeisure | 0:e0b964252a05 | 693 | |
Just4pLeisure | 0:e0b964252a05 | 694 | case '7': |
Just4pLeisure | 0:e0b964252a05 | 695 | case '8': |
Just4pLeisure | 0:e0b964252a05 | 696 | case '9': |
Just4pLeisure | 0:e0b964252a05 | 697 | sent = TRUE; |
Just4pLeisure | 0:e0b964252a05 | 698 | printf("and we're done :-) \r\n"); |
Just4pLeisure | 0:e0b964252a05 | 699 | break; |
Just4pLeisure | 0:e0b964252a05 | 700 | |
Just4pLeisure | 0:e0b964252a05 | 701 | // Some kind of invalid S-record type so break |
Just4pLeisure | 0:e0b964252a05 | 702 | default: |
Just4pLeisure | 0:e0b964252a05 | 703 | printf("oops - didn't recognise that S-Record \r\n"); |
Just4pLeisure | 0:e0b964252a05 | 704 | return FALSE; |
Just4pLeisure | 0:e0b964252a05 | 705 | // return SREC_FORMAT; |
Just4pLeisure | 0:e0b964252a05 | 706 | } |
Just4pLeisure | 0:e0b964252a05 | 707 | } |
Just4pLeisure | 0:e0b964252a05 | 708 | timer.stop(); |
Just4pLeisure | 0:e0b964252a05 | 709 | printf("Uploading the FLASH update file took %f seconds. \r\n",timer.read()); |
Just4pLeisure | 0:e0b964252a05 | 710 | fclose(fp); |
Just4pLeisure | 0:e0b964252a05 | 711 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 712 | } |
Just4pLeisure | 0:e0b964252a05 | 713 | |
Just4pLeisure | 0:e0b964252a05 | 714 | // |
Just4pLeisure | 0:e0b964252a05 | 715 | // Trionic5SendC3Message |
Just4pLeisure | 0:e0b964252a05 | 716 | // |
Just4pLeisure | 0:e0b964252a05 | 717 | // Sends a C3 Message to the T5 ECU. The reply should contain the last used FLASH address |
Just4pLeisure | 0:e0b964252a05 | 718 | // which is always 0x0007FFFF |
Just4pLeisure | 0:e0b964252a05 | 719 | // |
Just4pLeisure | 0:e0b964252a05 | 720 | // inputs: none |
Just4pLeisure | 0:e0b964252a05 | 721 | // return: bool TRUE if all went OK, |
Just4pLeisure | 0:e0b964252a05 | 722 | // |
Just4pLeisure | 0:e0b964252a05 | 723 | bool Trionic5SendC3Message() { |
Just4pLeisure | 0:e0b964252a05 | 724 | T5BootC3Command(); |
Just4pLeisure | 0:e0b964252a05 | 725 | T5WaitResponsePrint(); |
Just4pLeisure | 0:e0b964252a05 | 726 | printf("The Last used FLASH address message is:\r\n"); |
Just4pLeisure | 0:e0b964252a05 | 727 | return TRUE; |
Just4pLeisure | 0:e0b964252a05 | 728 | } |