Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Diff: t5can.cpp
- Revision:
- 5:1775b4b13232
- Parent:
- 3:92dae9083c83
diff -r 682d96ff6d79 -r 1775b4b13232 t5can.cpp --- a/t5can.cpp Wed Sep 11 11:55:51 2013 +0000 +++ b/t5can.cpp Sat Apr 25 17:07:08 2015 +0000 @@ -42,7 +42,8 @@ void t5_can_show_help(); void t5_can_show_full_help(); -void t5_can() { +void t5_can() +{ // Start the CAN bus system // Note that at the moment this is only for T5 ECUs at 615 kbits can_open(); @@ -103,7 +104,8 @@ @return command flag (success / failure) */ -uint8_t execute_t5_cmd() { +uint8_t execute_t5_cmd() +{ // uint8_t cmd_length = strlen(cmd_buffer); @@ -151,9 +153,10 @@ // Send a Bootloader file to the T5 ECU case 'b': + return (t5_can_send_boot_loader() && can_set_speed(1000000)) + ? TERM_OK : TERM_ERR; case 'B': - return (t5_can_send_boot_loader() && can_set_speed(1000000)) -// return (t5_can_send_boot_loader() && can_set_speed(615000)) + return (t5_can_send_boot_loader_S19() && can_set_speed(1000000)) ? TERM_OK : TERM_ERR; // Get Checksum from ECU (Bootloader must be uploaded first) @@ -186,8 +189,7 @@ return t5_can_dump_flash(T55FLASHSTART) ? TERM_OK : TERM_ERR; case 'D': - if (!t5_can_get_adaption_data()) - return TERM_ERR; +// if (!t5_can_send_boot_loader_S19()) if (!t5_can_send_boot_loader()) return TERM_ERR; can_set_speed(1000000); @@ -201,10 +203,12 @@ // Send a FLASH update file to the T5 ECU case 'f': - // NOTE 'f' command Just4TESTING! only FLASHes T5.5 ECU (with S19 type file) - return t5_can_send_flash_s19_update(T55FLASHSTART) + // NOTE 'f' command Just4TESTING! only FLASHes T5.5 ECU (with S19 type file) + //return t5_can_send_flash_s19_update(T55FLASHSTART) + return t5_can_send_flash_bin_update(T55FLASHSTART) ? TERM_OK : TERM_ERR; case 'F': +// if (!t5_can_send_boot_loader_S19()) if (!t5_can_send_boot_loader()) return TERM_ERR; can_set_speed(1000000); @@ -251,11 +255,12 @@ // inputs: none // return: none // -void t5_can_show_help() { +void t5_can_show_help() +{ printf("Trionic 5 Command Menu\r\n"); printf("======================\r\n"); - printf("D - Read SRAM adaption and DUMP T5 FLASH BIN file\r\n"); - printf("F - FLASH the update file to the T5 (and write SRAM - not done!)\r\n"); + printf("D - DUMP the T5.x ECU FLASH to a file 'ORIGINAL.BIN'\r\n"); + printf("F - FLASH the update file 'MODIFIED.BIN' to the T5.x\r\n"); printf("\r\n"); printf("r - read SRAM and write it to ADAPTION.RAM file\r\n"); printf("s - read Symbol Table and write it to SYMBOLS.TXT\r\n"); @@ -275,17 +280,18 @@ // inputs: none // return: none // -void t5_can_show_full_help() { +void t5_can_show_full_help() +{ printf("Trionic 5 Command Menu\r\n"); printf("======================\r\n"); - printf("D - Read SRAM adaption and DUMP T5 FLASH BIN file\r\n"); - printf("F - FLASH the update file to the T5 (and write SRAM - not done!)\r\n"); + printf("D - DUMP the T5.x ECU FLASH to a file 'ORIGINAL.BIN'\r\n"); + printf("F - FLASH the update file 'MODIFIED.BIN' to the T5.x\r\n"); printf("\r\n"); printf("b - upload and start MyBooty.S19 bootloader\r\n"); printf("c - get T5 ECU FLASH checksum (need to upload BOOTY.S19 before using this command)\r\n"); printf("d - dump the T5 FLASH BIN file and write it to ORIGINAL.BIN\r\n"); printf("e - erase the FLASH chips in the T5 ECU\r\n"); - printf("f - FLASH the update file MODIFIED.S19 to the T5 ECU\r\n"); + printf("f - FLASH the update file MODIFIED.BIN to the T5 ECU\r\n"); printf("r - read SRAM and write it to ADAPTION.RAM 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"); @@ -313,7 +319,8 @@ // inputs: none // return: bool TRUE if there was a message, FALSE if no message. // -bool t5_can_show_can_message() { +bool t5_can_show_can_message() +{ CANMessage can_MsgRx; if (can.read(can_MsgRx)) { printf("w%03x%d", can_MsgRx.id, can_MsgRx.len); @@ -336,7 +343,8 @@ // inputs: none // return: bool TRUE if there all went OK, FALSE if there was an error // -bool t5_can_get_symbol_table() { +bool t5_can_get_symbol_table() +{ printf("Saving the symbol table file\r\n"); FILE *fp = fopen("/local/symbols.txt", "w"); // Open "symbols.txt" on the local file system for writing if (!fp) { @@ -376,7 +384,8 @@ // inputs: none // return: bool TRUE if there all went OK, FALSE if there was an error // -bool t5_can_get_version() { +bool t5_can_get_version() +{ FILE *fp = fopen("/local/version.txt", "w"); // Open "version.txt" on the local file system for writing if (!fp) { perror ("The following error occured"); @@ -416,7 +425,8 @@ // inputs: none // return: bool TRUE if all went OK, FALSE if there was an error. // -bool t5_can_get_adaption_data() { +bool t5_can_get_adaption_data() +{ printf("Saving the SRAM adaption data.\r\n"); FILE *fp = fopen("/local/adaption.RAM", "w"); // Open "adaption.RAM" on the local file system for writing if (!fp) { @@ -468,7 +478,59 @@ // return: bool TRUE if all went OK, // FALSE if the 'bootloader' wasn't sent for some reason. // -bool t5_can_send_boot_loader() { +bool t5_can_send_boot_loader() +{ + uint32_t BootloaderSize = sizeof(T5BootLoader); + uint32_t address = MYBOOTY_START; // Start and execute from address of T5Bootloader + uint32_t count = 0; // progress count of bootloader bytes transferred + char msg[8]; // Construct the bootloader frame for uploading + + printf("Starting the bootloader.\r\n"); + while (count < BootloaderSize) { +// send a bootloader address message + if (!t5_can_send_boot_address((address+count), MYBOOTY_CHUNK)) return FALSE; +// send bootloader frames +// 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 +// is sent with the upload address) and ignores any extra bytes in the last frame. + for (uint8_t i=0; i<MYBOOTY_CHUNK; i++) { + msg[1+(i%7)] = T5BootLoader[count+i]; + if (i%7 == 0) msg[0]=i; // set the index number + if ((i%7 == 6) || (i == MYBOOTY_CHUNK-1 )) { + if (!t5_can_send_boot_frame(msg)) return FALSE; + } + } + count += MYBOOTY_CHUNK; + } +// These two lines really shouldn't be necessary but for some reason the first start +// command is ignored and a short delay is required before repeating. Using only a +// delay, even a very long one, doesn't work. +// +// NOTE: This measure isn't required when uploading an external S19 bootloader file! +// + T5StartBootLoader(address); + wait_ms(1); +// + return T5StartBootLoader(address); +} + + +// +// t5_can_send_boot_loader_S19 +// +// 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 t5_can_send_boot_loader_S19() +{ printf("Starting the bootloader.\r\n"); FILE *fp = fopen("/local/MyBooty.S19", "r"); // Open "booty.s19" on the local file system for reading if (!fp) { @@ -514,6 +576,7 @@ count--; } // send a bootloader address message +//// printf("address %x count %x\r\n",address ,count-1 ); if (!t5_can_send_boot_address(address, (count-1))) return FALSE; // 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 @@ -524,11 +587,13 @@ 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)) + if ((i%7 == 6) || (i == count - 2)) { +//// printf("Sending %2x %2x %2x %2x %2x %2x %2x %2x \r\n", msg[0], msg[1], msg[2], msg[3], msg[4], msg[5], msg[6], msg[7] ); if (!t5_can_send_boot_frame(msg)) { fclose(fp); return FALSE; } + } } // get the checksum if ((checksum += SRecGetByte(fp)) != 0xFF) { @@ -545,6 +610,7 @@ case '8': case '9': asize = 11 - (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 just the address and the checksum // so return with an error if other than this! if ((c = SRecGetByte(fp)) != (asize + 1)) break; @@ -604,7 +670,8 @@ // inputs: none // return: bool TRUE if all went OK, // -bool t5_can_get_checksum() { +bool t5_can_get_checksum() +{ uint32_t checksum = 0; if (!t5_boot_checksum_command(&checksum)) { printf("Error The ECU's checksum is wrong!\r\n"); @@ -622,7 +689,8 @@ // inputs: none // outputs: bool TRUE if all went OK. // -bool t5_can_bootloader_reset() { +bool t5_can_bootloader_reset() +{ printf("Exiting the bootloader and restarting the T5 ECU.\r\n"); if (!t5_boot_reset_command()) { printf("Error trying to reset the T5 ECU!\r\n"); @@ -670,7 +738,8 @@ // inputs: start T5 ecu start address // return: bool TRUE if all went OK. // -bool t5_can_get_start_and_chip_types(uint32_t* start) { +bool t5_can_get_start_and_chip_types(uint32_t* start) +{ *start = 0; uint8_t make = 0; uint8_t type = 0; @@ -689,23 +758,44 @@ case INTEL: printf("INTEL "); break; + case ATMEL: + printf("ATMEL "); + break; + case SST: + printf("SST "); + break; + case ST: + printf("ST "); + break; + case AMIC: + printf("AMIC "); + break; default: - printf("UNKNOWN FLASH chips - check pin65 has enough volts!\r\n"); + printf("\r\nUNKNOWN Manufacturer Id: %02x - Also check pin65 has enough volts!\r\n", make); } switch (type) { case AMD28F512: case INTEL28F512: printf("28F512 FLASH chips.\r\n"); break; + case ATMEL29C512: + printf("29C512 FLASH chips.\r\n"); + break; + case ATMEL29C010: + printf("29C010 FLASH chips.\r\n"); + break; case AMD28F010: case INTEL28F010: printf("28F010 FLASH chips.\r\n"); break; case AMD29F010: + case SST39SF010: +// case ST29F010: // Same as AMD29F010 + case AMICA29010L: printf("29F010 FLASH chips.\r\n"); break; default: - printf("UNKNOWN - check pin65 has enough volts!\r\n"); + printf("UNKNOWN Device Id: %02x - Also check pin65 has enough volts!\r\n", type); return FALSE; } return TRUE; @@ -739,7 +829,8 @@ // inputs: none // return: bool TRUE if all went OK. // -bool t5_can_erase_flash() { +bool t5_can_erase_flash() +{ printf("Erasing the FLASH chips.\r\n"); if (!t5_boot_erase_command()) { printf("Error The ECU's FLASH has not been erased!\r\n"); @@ -762,7 +853,8 @@ // return: bool TRUE if all went OK, FALSE if there was an error. // -bool t5_can_dump_flash(uint32_t start) { +bool t5_can_dump_flash(uint32_t start) +{ printf("Saving the original FLASH BIN file.\r\n"); FILE *fp = fopen("/local/original.bin", "w"); // Open "original.bin" on the local file system for writing if (!fp) { @@ -771,6 +863,7 @@ } uint32_t address = start + 5; // Mysterious reason for starting at 5 !!! char FLASHdata[6]; + printf(" 0.00 %% complete.\r"); while (address < TRIONICLASTADDR) { if (!t5_can_read_data(FLASHdata, address)) { fclose (fp); @@ -783,6 +876,7 @@ printf ("Error writing to the FLASH BIN file.\r\n"); return FALSE; } + printf("%6.2f\r", 100*(float)(address-start)/(float)(TRIONICLASTADDR - start) ); } // There are a few more bytes to get because because the bin file is not an exact multiple of 6 bytes! // the % (modulo) mathematics function tells us how many bytes there are still to get @@ -796,6 +890,7 @@ printf ("Error writing to the FLASH BIN file.\r\n"); return FALSE; } + printf("100.00 %% complete.\r\n"); fclose(fp); return TRUE; } @@ -804,7 +899,7 @@ // // t5_can_send_flash_bin_update // -// Sends a FLASH update file, modified.hex to the T5 ECU. +// Sends a FLASH update file, modified.bin to the T5 ECU. // The FLASH update file is stored on the local file system and must be in hex format. // // FLASHing a T5.5 ECU takes around 40 seconds. FLASHing T5.2 ECUs should take about half of this time @@ -814,11 +909,12 @@ // return: bool TRUE if all went OK, // FALSE if the FLASH update failed for some reason. // -bool t5_can_send_flash_bin_update(uint32_t start) { +bool t5_can_send_flash_bin_update(uint32_t start) +{ printf("Programming the FLASH chips.\r\n"); - FILE *fp = fopen("/local/modified.hex", "r"); // Open "modified.s19" on the local file system for reading + FILE *fp = fopen("/local/modified.bin", "r"); // Open "modified.bin" on the local file system for reading if (!fp) { - printf("Error: I could not find the BIN file MODIFIED.HEX\r\n"); + printf("Error: I could not find the BIN file MODIFIED.BIN\r\n"); return FALSE; } @@ -857,15 +953,15 @@ uint32_t curr_addr = start; // address to put FLASH data uint8_t byte_value = 0; + printf(" 0.00 %% complete.\r"); while (curr_addr <= TRIONICLASTADDR) { // send a bootloader address message if (!t5_can_send_boot_address(curr_addr, 0x80)) { fclose(fp); - printf("Error sending CAN message"); + printf("\r\nError sending Block Start message. Address: %08x\r\n",curr_addr); return FALSE; } - curr_addr += 0x80; // Construct and send the bootloader frames // 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 @@ -873,7 +969,7 @@ for (uint8_t i=0; i<0x80; i++) { if (!fread(&byte_value,1,1,fp)) { fclose(fp); - printf("Error reading the BIN file MODIFIED.HEX"); + printf("\r\nError reading the BIN file MODIFIED.BIN\r\n"); return FALSE; } msg[1+(i%7)] = byte_value; @@ -881,11 +977,15 @@ if ((i%7 == 6) || (i == 0x80 - 1)) if (!t5_can_send_boot_frame(msg)) { fclose(fp); - printf("Error sending CAN message"); + printf("\r\nError sending a Block data message. Address: %08x, Index: %02x\r\n",curr_addr, i); return FALSE; } + } + curr_addr += 0x80; + printf("%6.2f\r", 100*(float)(curr_addr - start)/(float)(TRIONICLASTADDR - start) ); } + printf("100.00 %% complete.\r\n"); fclose(fp); return TRUE; } @@ -903,7 +1003,8 @@ // return: bool TRUE if all went OK, // FALSE if the FLASH update failed for some reason. // -bool t5_can_send_flash_s19_update(uint32_t start) { +bool t5_can_send_flash_s19_update(uint32_t start) +{ printf("Programming the FLASH chips.\r\n"); FILE *fp = fopen("/local/modified.s19", "r"); // Open "modified.s19" on the local file system for reading if (!fp) { @@ -1014,7 +1115,8 @@ // inputs: none // return: bool TRUE if all went OK, // -bool t5_can_get_last_address() { +bool t5_can_get_last_address() +{ uint32_t last_address = 0; uint16_t mode = 0; if (!t5_boot_c3_command(&last_address, &mode)) {