Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Diff: Trionic5.cpp
- Revision:
- 1:d5452e398b76
- Parent:
- 0:e0b964252a05
- Child:
- 2:bf3a2b29259a
--- a/Trionic5.cpp Wed May 19 12:39:18 2010 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,728 +0,0 @@ -/******************************************************************************* - -Trionic5.cpp - By Sophie Dexter, April 2010 - -This C++ module provides functions for reading and writing the FLASH chips and -SRAM in Trionic5 ECUs. (Writing the adaption data back to SRAM not done yet). - -Some functions need an additional 'bootloader' program to be sent to the T5 ECU -before they can be used. These functions are: Identifying the T5 ECU type and -FLASH chips, dumping the FLASH chips, erasing the FLASH chips, writing to the -FLASH chips and calculating the FLASH chips' checksum. - -My version of the bootloader, BOOTY.S19, includes some features not in other -bootloaders; identifying the ECU and FLASH chip types, a 'safer' way of dumping -the FLASH chips and the ability to program AMD 29F010 type FLASH chips (NOTE -that AMD 29F010 FLASH programming is experimental at this stage to say the least) - -******************************************************************************** - -WARNING: Use at your own risk, sadly this software comes with no guarantees. -This software is provided 'free' and in good faith, but the author does not -accept liability for any damage arising from its use. - -*******************************************************************************/ - -#include "Trionic5.h" - -// RS232 on USB connection -Serial pc2(USBTX, USBRX); // tx, rx - -// A timer for timing how long things take to happen -Timer timer; - -// We use CAN on mbed pins 29(CAN_TXD) and 30(CAN_RXD). -CAN can_temp(p30, p29); - -// Need to create this to be able to read and write files on the mbed 'disk' -LocalFileSystem local("local"); - -void Trionic5() { - // Start the CAN bus system - // Note that at the moment this is only for T5 ECUs at 615 kbits - CANOpen(); - - int counter = 0; //counter used for testing things !?! - - Trionic5ShowHelp(); - - while (1) { - // send received messages to the pc over USB connection - // This function displays any CAN messages that are 'missed' by the other functions - // Can messages might be 'missed' because they are received after a 'timeout' period - // or because they weren't expected, e.g. if the T5 ECU resets for some reason - Trionic5ShowCANMessage(); - -// Wait for a single command character from the PC - if (pc2.readable()) { -// char command[30] = "w0068c600000000000000"; -// command = pc2.gets(); - char c = (pc2.getc()); - if ((c=='h') || (c=='H')) Trionic5ShowHelp(); // Print help - if (c=='\e') return; // 'ESC' key to go back to mbed CAN tool menu -// if ((c=='s') or (c=='S')) { - if (c=='s') Trionic5GetSymbolTable(); // Get the Symbol Table - if (c=='S') T5ReadCmnd(T5SYMBOLS); -// if ((c=='v') or (c=='V')) { - if (c=='v') Trionic5GetVersion(); // Get the Trionic5 software version string - if (c=='V') T5ReadCmnd(T5VERSION); -// if ((c=='r') or (c=='R')) { - if (c=='r') Trionic5GetAdaptionData(); // Read Adaption Data from RAM and write it to a file - if (c=='R') T5RAMCmnd(counter++); - if (c=='\r') T5ReadCmnd(CR); // CR - send CR type message - -// if ((c=='a') or (c=='A')) { - if (c=='a') { // Get a single symbol from the Symbol Table - char symbol[40]; - T5GetSymbol(symbol); - printf("%s",symbol); - } - if (c=='A') T5Ack(); // Just send an 'ACK' message - if ((c=='b') or (c=='B')) Trionic5SendBootLoader(); // Send a Bootloader file to the T5 ECU - if ((c=='c') or (c=='C')) Trionic5GetChecksum(); // Get Checksum from ECU (Bootloader must be uploaded first) - if ((c=='q') or (c=='Q')) Trionic5BootloaderReset(); // Exit the BootLoader and restart the T5 ECU - if ((c=='e') or (c=='E')) Trionic5EraseFLASH(); // Erase the FLASH chips - if ((c=='t') or (c=='T')) Trionic5GetChipTypes(); // Read back the FLASH chip types -// if ((c=='d') or (c=='D')) Trionic5DumpFLASH(); // DUMP the T5 ECU BIN file stored in the FLASH chips -// if (c=='d') Trionic5DumpFLASH(); // DUMP the T5 ECU BIN file stored in the FLASH chips -// if (c=='D') Trionic5DumpFLASH2(); // DUMP the T5 ECU BIN file stored in the FLASH chips - if ((c=='d') or (c=='D')) Trionic5DumpFLASH2(); // DUMP the T5 ECU BIN file stored in the FLASH chips - if ((c=='f') or (c=='F')) Trionic5SendFLASHUpdate(); // Send a FLASH update file to the T5 ECU - if (c=='3') Trionic5SendC3Message(); // Send the C3 message - should get last used address 0x7FFFF - } - } -} - -// -// Trionic5ShowHelp -// -// Displays a list of things that can be done with the T5 ECU. -// -// inputs: none -// return: none -// -void Trionic5ShowHelp() { - printf("Trionic 5 Command Menu\r\n"); - printf("======================\r\n"); - printf("b - upload and start MyBooty.S19 bootloader\r\n"); - printf("c - get T5 ECU FLASH checksum (need toupload BOOTY.S19 before using this command)\r\n"); - printf("d - dump the T5 FLASH BIN file and write it to ORIGINAL.HEX\r\n"); - printf("e - erase the FLASH chips in the T5 ECU\r\n"); - printf("f - FLASH the upate file MODIFIED.S19 to the T5 ECU\r\n"); - printf("e - erase the FLASH chips in the T5 ECU\r\n"); - printf("r - read SRAM and write it to ADAPTION.HEX file\r\n"); - printf("s - read Symbol Table, display it and write it to SYMBOLS.TXT\r\n"); - printf("v - read T5 ECU software version, display it and write it to VERSION.TXT\r\n"); - printf("q - exit the bootloader and reset the T5 ECU\r\n"); - printf("t - read the FLASH chip type in the T5 ECU\r\n"); - printf("3 - read the last used FLASH address in the T5 ECU\r\n"); - printf("S - send 's' message (to get symbol table)\r\n"); - printf("V - send 'S' message (to get software version)\r\n"); - printf("'Enter' Key - send an CR message\r\n"); - printf("a - send an ACK\r\n"); - printf("A - read a single symbol from the symbol table\r\n"); - printf("\r\n"); - printf("'ESC' - return to mbed CAN tool Menu\r\n"); - printf("\r\n"); - printf("h/H - show this help menu\r\n"); - return; -} - -// -// Trionic5ShowCANMessage -// -// Displays a CAN message in the RX buffer if there is one. -// -// inputs: none -// return: bool TRUE if there was a message, FALSE if no message. -// -bool Trionic5ShowCANMessage() { - CANMessage can_MsgRx; - if (can_temp.read(can_MsgRx)) { - printf("w%03x%d", can_MsgRx.id, can_MsgRx.len); - for (char i=0; i<can_MsgRx.len; i++) { - printf("%02x", can_MsgRx.data[i]); - } - printf(" %c ", can_MsgRx.data[2]); - printf("\r\n"); - return TRUE; - } - return FALSE; -} - -// -// Trionic5GetSymbolTable -// -// Gets the T5 ECU symbol table. -// The Symbol Table is sent to the PC and saved to a file, symbols.txt, on the mbed 'local' file system 'disk'. -// -// inputs: none -// return: bool TRUE if there all went OK, FALSE if there was an error -// -bool Trionic5GetSymbolTable() { - FILE *fp = fopen("/local/symbols.txt", "w"); // Open "symbols.txt" on the local file system for writing - if (!fp) return FALSE; - char symbol[40]; - char response = '\0'; - T5ReadCmnd(T5SYMBOLS); - response = T5WaitResponse(); - if (response != '>') - return FALSE; -// printf("%c",response); - T5ReadCmnd(CR); - response = T5WaitResponse(); - if (response != '>') - return FALSE; -// printf("%c",response); - timer.reset(); - timer.start(); - do { - T5GetSymbol(symbol); - printf("%s",symbol); - fprintf(fp,"%s",symbol); - } while (!StrCmp(symbol,"END\r\n")); - timer.stop(); - printf("Getting the Symbol Table took %f seconds.\r\n",timer.read()); - fclose(fp); - return TRUE; -} - -// -// Trionic5GetVersion -// -// Gets the T5 software version string. -// The software version is is sent to the PC and saved to a file, version.txt, on the mbed 'local' file system 'disk'. -// -// inputs: none -// return: bool TRUE if there all went OK, FALSE if there was an error -// -bool Trionic5GetVersion() { - FILE *fp = fopen("/local/version.txt", "w"); // Open "version.txt" on the local file system for writing - if (!fp) return FALSE; - char symbol[40]; - char response = '\0'; - T5ReadCmnd(T5VERSION); - response = T5WaitResponse(); - if (response != '>') - return FALSE; -// printf("%c",response); - T5ReadCmnd(CR); - response = T5WaitResponse(); - if (response != '>') - return FALSE; -// printf("%c",response); - T5GetSymbol(symbol); - printf("%s",symbol); - if (fp) - fprintf(fp,"%s",symbol); - else - printf("ERROR Could not open version.txt for saving\r\n"); - fclose(fp); - return TRUE; -} - -// -// Trionic5GetAdaptionData -// -// Gets the adaption data from the T5's SRAM. -// The adaption data is stored in a hex file, adaption.hex, on the mbed 'local' file system 'disk'. -// -// Reading the Adaption data from SRAM takes about 16 seconds. -// -// inputs: none -// return: bool TRUE if all went OK, FALSE if there was an error. -// -bool Trionic5GetAdaptionData() { - printf("getting adaption data\r\n"); - FILE *fp = fopen("/local/adaption.hex", "w"); // Open "adaption.hex" on the local file system for writing - if (!fp) return FALSE; - printf("opened adaption data file\r\n"); - unsigned int address = 5; // Mysterious reason for starting at 5 !!! - char RAMdata[6]; - timer.reset(); - timer.start(); - for (int i=0; i<5462; i++) { // Mysterious number 5462 is 0x8000 / 6 - rounded up !!! - T5ReadRAM(RAMdata, address); - address += 6; - for (int j=0; j<6; j++) { - if (((i*6) + j) < T5RAMSIZE) - fputc(RAMdata[j],fp); - } - } - timer.stop(); - printf("Getting the RAM Data took %f seconds.\r\n",timer.read()); - fclose(fp); - return TRUE; -} - -// -// Trionic5SendBootLoader -// -// Sends a 'bootloader' file, booty.s19 to the T5 ECU. -// The 'bootloader' is stored on the mbed 'local' file system 'disk' and must be in S19 format. -// -// The 'bootloader' is then able to dump or reFLASH the T5 ECU FLASH chips - this is the whole point of the exercise :-) -// -// Sending the 'bootloader' to the T5 ECU takes just over 1 second. -// -// inputs: none -// return: bool TRUE if all went OK, -// FALSE if the 'bootloader' wasn't sent for some reason. -// -bool Trionic5SendBootLoader() { - FILE *fp = fopen("/local/MyBooty.S19", "r"); // Open "booty.s19" on the local file system for reading - if (!fp) return FALSE; - int c = 0; // for some reason fgetc returns an int instead of a char - int count = 0; // count of bytes in the S-record can be 0xFF = 255 in decimal - int asize = 0; // 2,3 or 4 bytes in address - unsigned int address = 0; // address to put S-record - int checksum = 0; // checksum check at the end of each S-record line - char msg[8]; // Construct the bootloader frame for uploading - bool sent = FALSE; - - timer.reset(); - timer.start(); - while (!sent) { - - do c = fgetc (fp); // get characters until we get an 'S' (throws away \n,\r characters and other junk) - while (c != 'S' && c != EOF); -// if (c == EOF) return '\a'; - c = fgetc(fp); // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) -// if ((c = fgetc(fp)) == EOF) return '\a'; // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) - switch (c) { - case '0': - break; // Skip over S0 header record - - case '1': - case '2': - case '3': - asize = 1 + c - '0'; // 2, 3 or 4 bytes for address - address = 0; -// get the number of bytes (in ascii format) in this S-record line -// there must be at least the address and the checksum so return with an error if less than this! - if ((c = SRecGetByte(fp)) < (asize + 1)) break; -// if ((c = SRecGetByte(fp)) < 3) return '\a'; - count = c; - checksum = c; -// get the address - for (int i=0; i<asize; i++) { - c = SRecGetByte(fp); - checksum += c; - address <<= 8; - address |= c; - count--; - } -// send a bootloader address message - T5SendBootAddress(address, (count-1)); -// T5WaitResponsePrint(); - T5WaitResponse(); -// get and send the bootloader frames for this S-record -// 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 -// are repeated from the previous frame. This is OK because the T5 ECU knows how many bytes to expect (because the count of bytes -// in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame. - for (int i=0; i<count-1; i++) { - c = SRecGetByte(fp); - checksum += c; - msg[1+(i%7)] = c; - if (i%7 == 0) msg[0]=i; // set the index number - if ((i%7 == 6) || (i == count - 2)) { - T5SendBootFrame(msg); -// T5WaitResponsePrint(); - T5WaitResponse(); - } - } -// get the checksum - if (((checksum += SRecGetByte(fp)) | 0xFF) != 0xFF) break; -// if ((checksum += SRecGetByte(fp)) != 0xff) return '\a'; - break; - - case '5': - break; // Skip over S5 record types - - case '7': - case '8': - case '9': - asize = 11 - (c - '0'); // 2, 3 or 4 bytes for address -// get the number of bytes (in ascii format) in this S-record line there must be just the address and the checksum -// so return with an error if other than this! - printf("Starting the bootloader, "); - if ((c = SRecGetByte(fp)) != (asize + 1)) break; -// if ((c = SRecGetByte(fp)) < 3) return '\a'; - printf("so far so good"); - checksum = c; -// get the address - for (int i=0; i<asize; i++) { - c = SRecGetByte(fp); - checksum += c; - address <<= 8; - address |= c; - } - printf("calculated the address, "); -// get the checksum -// if (((checksum += SRecGetByte(fp)) | 0xFF) != 0xFF) break; -// if ((checksum += SRecGetByte(fp)) != 0xff) return '\a'; - printf("checksum is OK, "); - T5StartBootLoader(address); -// T5WaitResponsePrint(); - sent = TRUE; - printf("and we're done :-) \r\n"); - break; - -// Some kind of invalid S-record type so break - default: - printf("oops - didn't recognise that S-Record \r\n"); - return FALSE; -// return SREC_FORMAT; - } - } - timer.stop(); - printf("Uploading and starting the bootloader took %f seconds. \r\n",timer.read()); - fclose(fp); - return TRUE; -} - -// -// Trionic5GetChecksum -// -// Calculates the checksum of the FLASH in the T5 ECU. -// The 'bootloader', booty.s19, must be loaded before this function can be used. -// The 'bootloader' actually calculates the checksum and compares it with the -// value stored in the 'header' region at the end of the FLASH. -// -// The bootloader sends a single CAN message with the result e.g. -// w00C8C800CAFEBABE0808 -// 00C - T5 response messages have an CAN id of 00C -// 8 - All T5 messages have a message length of 8 bytes -// C8 - This is the checksum message type -// 00 - 00 means OK, the checksum calculation matches the stored value which in this case is: -// CAFEBABE - lol :-) -// -// w00C8C801FFFFFFFF0808 -// 01 - 01 means calculated value doesn't matched the stored value -// FFFFFFFF - in this case the stored value is FFFFFFFF - the chips might be erased -// -// Calculating the checksum takes a little under 2 seconds. -// -// inputs: none -// return: bool TRUE if all went OK, -// -bool Trionic5GetChecksum() { - timer.reset(); - timer.start(); - T5BootCSumCmnd(); - T5WaitResponsePrint(); - timer.stop(); - printf("T5 ECU took took %f seconds to calculate it's checksum.\r\n",timer.read()); - return TRUE; -} - -// -// Trionic5BootloaderReset -// -// Exits the Bootloader and restart the T5 ECU -// -// inputs: none -// outputs: bool TRUE if all went OK. -// -bool Trionic5BootloaderReset() { - T5BootResetCmnd(); - T5WaitResponsePrint(); - return TRUE; -} - -// -// Trionic5GetChipTypes -// -// Gets the FLASH chip type fitted. -// -// NOTE the bootloader must be loaded in order to use this function. -// -// CAN messages from the T5 ECU with FLASH data look like this: -// -// C9,00,aa,aa,aa,aa,mm,dd, -// -// C9 lets us know its a FLASH id message -// -// 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 -// 0x00020000 - T5.2 -// 0x00040000 - T5.5 -// -// mm = Manufacturer id. These can be: -// 0x89 - Intel -// 0x31 - CSI/CAT -// 0x01 - AMD -// 0x1F - Atmel -// -// dd = Device id. These can be: -// 0xB8 - Intel _or_ CSI 28F512 (Fiited by Saab in T5.2) -// 0xB4 - Intel _or_ CSI 28F010 (Fitted by Saab in T5.5) -// 0x25 - AMD 28F512 (Fiited by Saab in T5.2) -// 0xA7 - AMD 28F010 (Fitted by Saab in T5.5) -// 0x20 - AMD 29F010 (Some people have put these in their T5.5) -// 0x5D - Atmel 29C512 (Some people mave have put these in their T5.2) -// 0xD5 - Atmel 29C010 (Some people have put these in their T5.5) -// -// mm = 0xFF, dd == 0xF7 probably means that the programming voltage isn't right. -// -// Finding out which ECU type and FLASH chips are fitted takes under a second. -// -// inputs: none -// return: bool TRUE if all went OK. -// -bool Trionic5GetChipTypes() { - timer.reset(); - timer.start(); - T5BootFLASHType(); - T5WaitResponsePrint(); - timer.stop(); - printf("Getting the FLASH chip id took %f seconds.\r\n",timer.read()); - return TRUE; -} - -// -// Trionic5EraseFLASH -// -// Erases the FLASH Chips. -// -// NOTE the bootloader must be loaded in order to use this function. -// -// CAN messages from the T5 ECU with FLASH erase command look like this: -// -// C0,cc,08,08,08,08,08,08 -// -// C0 tells us this is a response to the FLASH erase command. -// -// cc is a code that tells us what happened: -// 00 - FLASH was erased OK -// 01 - Could not erase FLASH chips to 0xFF -// 02 - Could not write 0x00 to 28F FLASH chips -// 03 - Unrecognised FLASH chip type (or maybe programming voltage isn't right) -// 04 - Intel chips found, but unrecognised type -// 05 - AMD chips found, but unrecognised type -// 06 - CSI/Catalyst chips found, but unrecognised type -// 07 - Atmel chips found - Atmel chips don't need to be erased -// -// Erasing 28F type FLASH chips takes around 22 seconds. 29F chips should be erased much more quickly. -// -// inputs: none -// return: bool TRUE if all went OK. -// -bool Trionic5EraseFLASH() { - timer.reset(); - timer.start(); - T5BootEraseCmnd(); - T5WaitResponsePrint(); - timer.stop(); - printf("Erasing the FLASH took %f seconds.\r\n",timer.read()); - return TRUE; -} - -// -// Trionic5DumpFLASH -// -// Dumps the FLASH chip BIN file, original.hex to the mbed 'disk' -// -// NOTE the bootloader must be loaded in order to use this function. -// -// CAN messages from the T5 ECU with FLASH data look like this: -// -// A6,mm,dd,dd,dd,dd,08,08 -// -// A6 lets us know its a FLASH data message -// mm tells us if there is any more data -// mm == 04 means at least 4 more bytes to come -// mm == 00 means that these are the last FLASH data bytes -// dd,dd,dd,dd are 4 FLASH data bytes -// The last 2 bytes are 08,08 they aren't and don't meean anything -// (It would be more efficient to dump 6 bytes at a time because less -// CAN messages would be needed but it was easier to write the -// bootloader to send just 4 bytes so that's what I did) -// -// Dumping FLASH chips in a T5.5 ECU takes around 88 seconds. Dumping T5.2 ECUs should take about half of this time -// -// inputs: none -// return: bool TRUE if all went OK. -// -bool Trionic5DumpFLASH() { - printf("getting FLASH BIN file\r\n"); - FILE *fp = fopen("/local/original.hex", "w"); // Open "original.hex" on the local file system for writing - if (!fp) return FALSE; - printf("opened FLASH BIN file\r\n"); - char FLASHdata[8]; - timer.reset(); - timer.start(); -// int count = 0; - do { - T5BootDumpFLASHCmnd(); -// T5WaitResponsePrint(); - T5WaitFLASH(FLASHdata); - for (int j=0; j<4; j++) { - fputc(FLASHdata[j+2],fp); -// count++; - } - } while (FLASHdata[1] != 0); - timer.stop(); -// printf("count = 0x%x\r\n", count); - printf("Getting the FLASH BIN took %f seconds.\r\n",timer.read()); - fclose(fp); - return TRUE; -} - - -// -// Trionic5DumpFLASH2 -// -// Gets the adaption data from the T5's SRAM. -// The adaption data is stored in a hex file, adaption.hex, on the mbed 'local' file system 'disk'. -// -// Reading the Adaption data from SRAM takes about 16 seconds. -// -// inputs: none -// return: bool TRUE if all went OK, FALSE if there was an error. -// -bool Trionic5DumpFLASH2() { - printf("getting FLASH BIN file\r\n"); - FILE *fp = fopen("/local/original.hex", "w"); // Open "adaption.hex" on the local file system for writing - if (!fp) return FALSE; - printf("opened FLASH BIN file\r\n"); - unsigned int address = 0x40005; // Mysterious reason for starting at 5 !!! - char FLASHdata[6]; - timer.reset(); - timer.start(); - for (int i=0; i<43690; i++) { // Mysterious number 43690 is 0x40000 / 6 - T5ReadFLASH(FLASHdata, address); - address += 6; - for (int j=0; j<6; j++) { - fputc(FLASHdata[j],fp); - } - } - address = 0x7FFFF; - T5ReadFLASH(FLASHdata, address); - for (int j=0; j<4; j++) { - fputc(FLASHdata[j+2],fp); - } - timer.stop(); - printf("Getting the FLASH BIN took %f seconds.\r\n",timer.read()); - fclose(fp); - return TRUE; -} - -// -// Trionic5SendFLASHUpdate -// -// Sends a FLASH update file, modified.s19 to the T5 ECU. -// The FLASH update file is stored on the local file system and must be in S19 format. -// -// FLASHing a T5.5 ECU takes around 90 seconds. FLASHing T5.2 ECUs should take about half of this time -// -// inputs: none -// return: bool TRUE if all went OK, -// FALSE if the FLASH update failed for some reason. -// -bool Trionic5SendFLASHUpdate() { - FILE *fp = fopen("/local/modified.s19", "r"); // Open "modified.s19" on the local file system for reading - if (!fp) return FALSE; - printf("Opened MODIFIED.S19 "); - int c = 0; // for some reason fgetc returns an int instead of a char - int count = 0; // count of bytes in the S-record can be 0xFF = 255 in decimal - int asize = 0; // 2,3 or 4 bytes in address - unsigned int address = 0; // address to put S-record - int checksum = 0; // checksum check at the end - char msg[8]; // Construct the bootloader frame for uploading - bool sent = FALSE; - - timer.reset(); - timer.start(); - while (!sent) { - - do c = fgetc (fp); // get characters until we get an 'S' (throws away \n,\r characters and other junk) - while (c != 'S' && c != EOF); -// if (c == EOF) return '\a'; - c = fgetc(fp); // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) -// if ((c = fgetc(fp)) == EOF) return '\a'; // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached) - switch (c) { - case '0': - break; // Skip over S0 header record - - case '1': - case '2': - case '3': - asize = 1 + c - '0'; // 2, 3 or 4 bytes for address - address = 0; -// get the number of bytes (in ascii format) in this S-record line -// there must be at least the address and the checksum so return with an error if less than this! - if ((c = SRecGetByte(fp)) < (asize + 1)) break; -// if ((c = SRecGetByte(fp)) < 3) return '\a'; - count = c; - checksum = c; -// get the address - for (int i=0; i<asize; i++) { - c = SRecGetByte(fp); - checksum += c; - address <<= 8; - address |= c; - count--; - } - address += 0x40000; // Only for T5.5 at the moment !!! -// send a bootloader address message - T5SendBootAddress(address, (count-1)); -// T5WaitResponsePrint(); - T5WaitResponse(); -// get and send the bootloader frames for this S-record -// 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 -// are repeated from the previous frame. This is OK because the T5 ECU knows how many bytes to expect (because the count of bytes -// in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame. - for (int i=0; i<count-1; i++) { - c = SRecGetByte(fp); - checksum += c; - msg[1+(i%7)] = c; - if (i%7 == 0) msg[0]=i; // set the index number - if ((i%7 == 6) || (i == count - 2)) { - T5SendBootFrame(msg); -// T5WaitResponsePrint(); - T5WaitResponse(); - } - } -// get the checksum - if (((checksum += SRecGetByte(fp)) | 0xFF) != 0xFF) break; -// if ((checksum += SRecGetByte(fp)) != 0xff) return '\a'; - break; - - case '5': - break; // Skip over S5 record types - - case '7': - case '8': - case '9': - sent = TRUE; - printf("and we're done :-) \r\n"); - break; - -// Some kind of invalid S-record type so break - default: - printf("oops - didn't recognise that S-Record \r\n"); - return FALSE; -// return SREC_FORMAT; - } - } - timer.stop(); - printf("Uploading the FLASH update file took %f seconds. \r\n",timer.read()); - fclose(fp); - return TRUE; -} - -// -// Trionic5SendC3Message -// -// Sends a C3 Message to the T5 ECU. The reply should contain the last used FLASH address -// which is always 0x0007FFFF -// -// inputs: none -// return: bool TRUE if all went OK, -// -bool Trionic5SendC3Message() { - T5BootC3Command(); - T5WaitResponsePrint(); - printf("The Last used FLASH address message is:\r\n"); - return TRUE; -}