Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Committer:
Just4pLeisure
Date:
Wed May 19 12:39:18 2010 +0000
Revision:
0:e0b964252a05

        

Who changed what in which revision?

UserRevisionLine numberNew 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 }