Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Committer:
Just4pLeisure
Date:
Sat Apr 23 18:31:40 2016 +0000
Revision:
6:2fbcbebed28c
Parent:
5:1775b4b13232
Version 1.6 Faster T7 P-BUS FLASHing algorithm, longer T8 erase timeout fixed BDM register display function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Just4pLeisure 1:d5452e398b76 1 /*******************************************************************************
Just4pLeisure 1:d5452e398b76 2
Just4pLeisure 1:d5452e398b76 3 trionic5.cpp - CAN Bus functions for Just4Trionic by Just4pLeisure
Just4pLeisure 1:d5452e398b76 4 (c) 2010 by Sophie Dexter
Just4pLeisure 1:d5452e398b76 5
Just4pLeisure 1:d5452e398b76 6 This C++ module provides functions for reading and writing the FLASH chips and
Just4pLeisure 1:d5452e398b76 7 SRAM in Trionic5 ECUs. (Writing the adaption data back to SRAM not done yet).
Just4pLeisure 1:d5452e398b76 8
Just4pLeisure 1:d5452e398b76 9 Some functions need an additional 'bootloader' program to be sent to the T5 ECU
Just4pLeisure 1:d5452e398b76 10 before they can be used. These functions are: Identifying the T5 ECU type and
Just4pLeisure 1:d5452e398b76 11 FLASH chips, dumping the FLASH chips, erasing the FLASH chips, writing to the
Just4pLeisure 1:d5452e398b76 12 FLASH chips and calculating the FLASH chips' checksum.
Just4pLeisure 1:d5452e398b76 13
Just4pLeisure 1:d5452e398b76 14 My version of the bootloader, BOOTY.S19, includes some features not in other
Just4pLeisure 1:d5452e398b76 15 bootloaders; identifying the ECU and FLASH chip types, a 'safer' way of dumping
Just4pLeisure 1:d5452e398b76 16 the FLASH chips and the ability to program AMD 29F010 type FLASH chips
Just4pLeisure 1:d5452e398b76 17
Just4pLeisure 1:d5452e398b76 18 ********************************************************************************
Just4pLeisure 1:d5452e398b76 19
Just4pLeisure 1:d5452e398b76 20 WARNING: Use at your own risk, sadly this software comes with no guarantees.
Just4pLeisure 1:d5452e398b76 21 This software is provided 'free' and in good faith, but the author does not
Just4pLeisure 1:d5452e398b76 22 accept liability for any damage arising from its use.
Just4pLeisure 1:d5452e398b76 23
Just4pLeisure 1:d5452e398b76 24 *******************************************************************************/
Just4pLeisure 1:d5452e398b76 25
Just4pLeisure 1:d5452e398b76 26 #include "t5can.h"
Just4pLeisure 1:d5452e398b76 27
Just4pLeisure 1:d5452e398b76 28 // constants
Just4pLeisure 1:d5452e398b76 29 #define CMD_BUF_LENGTH 32 ///< command buffer size
Just4pLeisure 1:d5452e398b76 30
Just4pLeisure 1:d5452e398b76 31 // static variables
Just4pLeisure 1:d5452e398b76 32 static char cmd_buffer[CMD_BUF_LENGTH]; ///< command string buffer
Just4pLeisure 1:d5452e398b76 33
Just4pLeisure 1:d5452e398b76 34 //static uint32_t cmd_addr; ///< address (optional)
Just4pLeisure 1:d5452e398b76 35 //static uint32_t cmd_value; ///< value (optional)
Just4pLeisure 1:d5452e398b76 36 //static uint32_t cmd_result; ///< result
Just4pLeisure 1:d5452e398b76 37
Just4pLeisure 1:d5452e398b76 38 static uint32_t flash_start = 0;
Just4pLeisure 1:d5452e398b76 39
Just4pLeisure 1:d5452e398b76 40 // private functions
Just4pLeisure 1:d5452e398b76 41 uint8_t execute_t5_cmd();
Just4pLeisure 1:d5452e398b76 42 void t5_can_show_help();
Just4pLeisure 1:d5452e398b76 43 void t5_can_show_full_help();
Just4pLeisure 1:d5452e398b76 44
Just4pLeisure 5:1775b4b13232 45 void t5_can()
Just4pLeisure 5:1775b4b13232 46 {
Just4pLeisure 1:d5452e398b76 47 // Start the CAN bus system
Just4pLeisure 1:d5452e398b76 48 // Note that at the moment this is only for T5 ECUs at 615 kbits
Just4pLeisure 1:d5452e398b76 49 can_open();
Just4pLeisure 1:d5452e398b76 50 can_set_speed(615000);
Just4pLeisure 1:d5452e398b76 51
Just4pLeisure 1:d5452e398b76 52 t5_can_show_help();
Just4pLeisure 1:d5452e398b76 53
Just4pLeisure 1:d5452e398b76 54 // main loop
Just4pLeisure 1:d5452e398b76 55 *cmd_buffer = '\0';
Just4pLeisure 1:d5452e398b76 56 char ret;
Just4pLeisure 1:d5452e398b76 57 char rx_char;
Just4pLeisure 1:d5452e398b76 58 while (true) {
Just4pLeisure 1:d5452e398b76 59 // read chars from USB
Just4pLeisure 1:d5452e398b76 60 // send received messages to the pc over USB connection
Just4pLeisure 1:d5452e398b76 61 // This function displays any CAN messages that are 'missed' by the other functions
Just4pLeisure 1:d5452e398b76 62 // Can messages might be 'missed' because they are received after a 'timeout' period
Just4pLeisure 1:d5452e398b76 63 // or because they weren't expected, e.g. if the T5 ECU resets for some reason
Just4pLeisure 1:d5452e398b76 64 t5_can_show_can_message();
Just4pLeisure 1:d5452e398b76 65 if (pc.readable()) {
Just4pLeisure 1:d5452e398b76 66 // turn Error LED off for next command
Just4pLeisure 1:d5452e398b76 67 led4 = 0;
Just4pLeisure 1:d5452e398b76 68 rx_char = pc.getc();
Just4pLeisure 1:d5452e398b76 69 switch (rx_char) {
Just4pLeisure 1:d5452e398b76 70 // 'ESC' key to go back to mbed Just4Trionic 'home' menu
Just4pLeisure 1:d5452e398b76 71 case '\e':
Just4pLeisure 1:d5452e398b76 72 can_close();
Just4pLeisure 1:d5452e398b76 73 return;
Just4pLeisure 1:d5452e398b76 74 // end-of-command reached
Just4pLeisure 1:d5452e398b76 75 case TERM_OK :
Just4pLeisure 1:d5452e398b76 76 // execute command and return flag via USB
Just4pLeisure 1:d5452e398b76 77 timer.reset();
Just4pLeisure 1:d5452e398b76 78 timer.start();
Just4pLeisure 1:d5452e398b76 79 ret = execute_t5_cmd();
Just4pLeisure 1:d5452e398b76 80 pc.putc(ret);
Just4pLeisure 3:92dae9083c83 81 printf("Completed in %.3f seconds.\r\n", timer.read());
Just4pLeisure 1:d5452e398b76 82 // reset command buffer
Just4pLeisure 1:d5452e398b76 83 *cmd_buffer = '\0';
Just4pLeisure 1:d5452e398b76 84 // light up LED
Just4pLeisure 1:d5452e398b76 85 // ret == TERM_OK ? led_on(LED_ACT) : led_on(LED_ERR);
Just4pLeisure 1:d5452e398b76 86 ret == TERM_OK ? led3 = 1 : led4 = 1;
Just4pLeisure 1:d5452e398b76 87 break;
Just4pLeisure 1:d5452e398b76 88 // another command char
Just4pLeisure 1:d5452e398b76 89 default:
Just4pLeisure 1:d5452e398b76 90 // store in buffer if space permits
Just4pLeisure 1:d5452e398b76 91 if (StrLen(cmd_buffer) < CMD_BUF_LENGTH - 1) {
Just4pLeisure 1:d5452e398b76 92 StrAddc(cmd_buffer, rx_char);
Just4pLeisure 1:d5452e398b76 93 }
Just4pLeisure 1:d5452e398b76 94 break;
Just4pLeisure 1:d5452e398b76 95 }
Just4pLeisure 1:d5452e398b76 96 }
Just4pLeisure 1:d5452e398b76 97 }
Just4pLeisure 1:d5452e398b76 98 }
Just4pLeisure 1:d5452e398b76 99
Just4pLeisure 1:d5452e398b76 100 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 101 /**
Just4pLeisure 1:d5452e398b76 102 Executes a command and returns result flag (does not transmit the flag
Just4pLeisure 1:d5452e398b76 103 itself).
Just4pLeisure 1:d5452e398b76 104
Just4pLeisure 1:d5452e398b76 105 @return command flag (success / failure)
Just4pLeisure 1:d5452e398b76 106 */
Just4pLeisure 5:1775b4b13232 107 uint8_t execute_t5_cmd()
Just4pLeisure 5:1775b4b13232 108 {
Just4pLeisure 1:d5452e398b76 109
Just4pLeisure 1:d5452e398b76 110
Just4pLeisure 1:d5452e398b76 111 // uint8_t cmd_length = strlen(cmd_buffer);
Just4pLeisure 1:d5452e398b76 112 // command groups
Just4pLeisure 1:d5452e398b76 113 switch (*cmd_buffer) {
Just4pLeisure 1:d5452e398b76 114 // CHECK_ARGLENGTH(0);
Just4pLeisure 1:d5452e398b76 115 // Get the Symbol Table
Just4pLeisure 1:d5452e398b76 116 case 's':
Just4pLeisure 1:d5452e398b76 117 return t5_can_get_symbol_table()
Just4pLeisure 1:d5452e398b76 118 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 119 case 'S':
Just4pLeisure 1:d5452e398b76 120 return T5ReadCmnd(T5SYMBOLS)
Just4pLeisure 1:d5452e398b76 121 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 122
Just4pLeisure 1:d5452e398b76 123 // Get the Trionic5 software version string
Just4pLeisure 1:d5452e398b76 124 case 'v':
Just4pLeisure 1:d5452e398b76 125 return t5_can_get_version()
Just4pLeisure 1:d5452e398b76 126 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 127 case 'V':
Just4pLeisure 1:d5452e398b76 128 return T5ReadCmnd(T5VERSION)
Just4pLeisure 1:d5452e398b76 129 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 130
Just4pLeisure 1:d5452e398b76 131 // Read Adaption Data from RAM and write it to a file
Just4pLeisure 1:d5452e398b76 132 case 'r':
Just4pLeisure 1:d5452e398b76 133 case 'R':
Just4pLeisure 1:d5452e398b76 134 return t5_can_get_adaption_data()
Just4pLeisure 1:d5452e398b76 135 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 136
Just4pLeisure 1:d5452e398b76 137 // CR - send CR type message
Just4pLeisure 1:d5452e398b76 138 case '\0':
Just4pLeisure 1:d5452e398b76 139 return T5ReadCmnd(CR)
Just4pLeisure 1:d5452e398b76 140 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 141
Just4pLeisure 1:d5452e398b76 142 // Get a single symbol from the Symbol Table
Just4pLeisure 1:d5452e398b76 143 case 'a':
Just4pLeisure 1:d5452e398b76 144 char symbol[40];
Just4pLeisure 1:d5452e398b76 145 T5GetSymbol(symbol);
Just4pLeisure 1:d5452e398b76 146 printf("%s",symbol);
Just4pLeisure 1:d5452e398b76 147 return TERM_OK;
Just4pLeisure 1:d5452e398b76 148
Just4pLeisure 1:d5452e398b76 149 // Just send an 'ACK' message
Just4pLeisure 1:d5452e398b76 150 case 'A':
Just4pLeisure 1:d5452e398b76 151 return T5Ack()
Just4pLeisure 1:d5452e398b76 152 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 153
Just4pLeisure 1:d5452e398b76 154 // Send a Bootloader file to the T5 ECU
Just4pLeisure 1:d5452e398b76 155 case 'b':
Just4pLeisure 5:1775b4b13232 156 return (t5_can_send_boot_loader() && can_set_speed(1000000))
Just4pLeisure 5:1775b4b13232 157 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 158 case 'B':
Just4pLeisure 5:1775b4b13232 159 return (t5_can_send_boot_loader_S19() && can_set_speed(1000000))
Just4pLeisure 1:d5452e398b76 160 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 161
Just4pLeisure 1:d5452e398b76 162 // Get Checksum from ECU (Bootloader must be uploaded first)
Just4pLeisure 1:d5452e398b76 163 case 'c':
Just4pLeisure 1:d5452e398b76 164 case 'C':
Just4pLeisure 1:d5452e398b76 165 return t5_can_get_checksum()
Just4pLeisure 1:d5452e398b76 166 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 167
Just4pLeisure 1:d5452e398b76 168 // Exit the BootLoader and restart the T5 ECU
Just4pLeisure 1:d5452e398b76 169 case 'q':
Just4pLeisure 1:d5452e398b76 170 case 'Q':
Just4pLeisure 3:92dae9083c83 171 return (t5_can_bootloader_reset() && can_set_speed(615000))
Just4pLeisure 1:d5452e398b76 172 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 173
Just4pLeisure 1:d5452e398b76 174 // Erase the FLASH chips
Just4pLeisure 1:d5452e398b76 175 case 'e':
Just4pLeisure 1:d5452e398b76 176 case 'E':
Just4pLeisure 1:d5452e398b76 177 return t5_can_erase_flash()
Just4pLeisure 1:d5452e398b76 178 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 179
Just4pLeisure 1:d5452e398b76 180 // Read back the FLASH chip types
Just4pLeisure 1:d5452e398b76 181 case 't':
Just4pLeisure 1:d5452e398b76 182 case 'T':
Just4pLeisure 1:d5452e398b76 183 return t5_can_get_start_and_chip_types(&flash_start)
Just4pLeisure 1:d5452e398b76 184 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 185
Just4pLeisure 1:d5452e398b76 186 // DUMP the T5 ECU BIN file stored in the FLASH chips
Just4pLeisure 1:d5452e398b76 187 case 'd':
Just4pLeisure 1:d5452e398b76 188 // NOTE 'd' command Just4TESTING! only dumps T5.5 ECU
Just4pLeisure 1:d5452e398b76 189 return t5_can_dump_flash(T55FLASHSTART)
Just4pLeisure 1:d5452e398b76 190 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 191 case 'D':
Just4pLeisure 5:1775b4b13232 192 // if (!t5_can_send_boot_loader_S19())
Just4pLeisure 1:d5452e398b76 193 if (!t5_can_send_boot_loader())
Just4pLeisure 1:d5452e398b76 194 return TERM_ERR;
Just4pLeisure 3:92dae9083c83 195 can_set_speed(1000000);
Just4pLeisure 1:d5452e398b76 196 if (!t5_can_get_start_and_chip_types(&flash_start)) {
Just4pLeisure 1:d5452e398b76 197 t5_can_bootloader_reset();
Just4pLeisure 3:92dae9083c83 198 can_set_speed(615000);
Just4pLeisure 1:d5452e398b76 199 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 200 }
Just4pLeisure 3:92dae9083c83 201 return (t5_can_dump_flash(flash_start) && t5_can_bootloader_reset() && can_set_speed(615000))
Just4pLeisure 1:d5452e398b76 202 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 203
Just4pLeisure 1:d5452e398b76 204 // Send a FLASH update file to the T5 ECU
Just4pLeisure 1:d5452e398b76 205 case 'f':
Just4pLeisure 5:1775b4b13232 206 // NOTE 'f' command Just4TESTING! only FLASHes T5.5 ECU (with S19 type file)
Just4pLeisure 5:1775b4b13232 207 //return t5_can_send_flash_s19_update(T55FLASHSTART)
Just4pLeisure 5:1775b4b13232 208 return t5_can_send_flash_bin_update(T55FLASHSTART)
Just4pLeisure 1:d5452e398b76 209 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 210 case 'F':
Just4pLeisure 5:1775b4b13232 211 // if (!t5_can_send_boot_loader_S19())
Just4pLeisure 1:d5452e398b76 212 if (!t5_can_send_boot_loader())
Just4pLeisure 1:d5452e398b76 213 return TERM_ERR;
Just4pLeisure 3:92dae9083c83 214 can_set_speed(1000000);
Just4pLeisure 1:d5452e398b76 215 if (!t5_can_get_start_and_chip_types(&flash_start)) {
Just4pLeisure 1:d5452e398b76 216 t5_can_bootloader_reset();
Just4pLeisure 3:92dae9083c83 217 can_set_speed(615000);
Just4pLeisure 1:d5452e398b76 218 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 219 }
Just4pLeisure 1:d5452e398b76 220 if (!t5_can_get_checksum())
Just4pLeisure 1:d5452e398b76 221 led4 = 1;
Just4pLeisure 1:d5452e398b76 222 if (!t5_can_erase_flash()) {
Just4pLeisure 1:d5452e398b76 223 t5_can_bootloader_reset();
Just4pLeisure 3:92dae9083c83 224 can_set_speed(615000);
Just4pLeisure 1:d5452e398b76 225 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 226 }
Just4pLeisure 3:92dae9083c83 227 return (t5_can_send_flash_bin_update(flash_start) && t5_can_get_checksum() && t5_can_bootloader_reset() && can_set_speed(615000))
Just4pLeisure 1:d5452e398b76 228 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 229
Just4pLeisure 1:d5452e398b76 230 // Send the C3 message - should get last used address 0x7FFFF
Just4pLeisure 1:d5452e398b76 231 case '3':
Just4pLeisure 1:d5452e398b76 232 return t5_can_get_last_address()
Just4pLeisure 1:d5452e398b76 233 ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 234
Just4pLeisure 1:d5452e398b76 235 // Print help
Just4pLeisure 1:d5452e398b76 236 case 'h':
Just4pLeisure 1:d5452e398b76 237 t5_can_show_help();
Just4pLeisure 1:d5452e398b76 238 return TERM_OK;
Just4pLeisure 1:d5452e398b76 239 case 'H':
Just4pLeisure 1:d5452e398b76 240 t5_can_show_full_help();
Just4pLeisure 1:d5452e398b76 241 return TERM_OK;
Just4pLeisure 1:d5452e398b76 242 default:
Just4pLeisure 1:d5452e398b76 243 t5_can_show_help();
Just4pLeisure 1:d5452e398b76 244 break;
Just4pLeisure 1:d5452e398b76 245 }
Just4pLeisure 1:d5452e398b76 246 // unknown command
Just4pLeisure 1:d5452e398b76 247 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 248 }
Just4pLeisure 1:d5452e398b76 249
Just4pLeisure 1:d5452e398b76 250 //
Just4pLeisure 1:d5452e398b76 251 // Trionic5ShowHelp
Just4pLeisure 1:d5452e398b76 252 //
Just4pLeisure 1:d5452e398b76 253 // Displays a list of things that can be done with the T5 ECU.
Just4pLeisure 1:d5452e398b76 254 //
Just4pLeisure 1:d5452e398b76 255 // inputs: none
Just4pLeisure 1:d5452e398b76 256 // return: none
Just4pLeisure 1:d5452e398b76 257 //
Just4pLeisure 5:1775b4b13232 258 void t5_can_show_help()
Just4pLeisure 5:1775b4b13232 259 {
Just4pLeisure 1:d5452e398b76 260 printf("Trionic 5 Command Menu\r\n");
Just4pLeisure 1:d5452e398b76 261 printf("======================\r\n");
Just4pLeisure 5:1775b4b13232 262 printf("D - DUMP the T5.x ECU FLASH to a file 'ORIGINAL.BIN'\r\n");
Just4pLeisure 5:1775b4b13232 263 printf("F - FLASH the update file 'MODIFIED.BIN' to the T5.x\r\n");
Just4pLeisure 1:d5452e398b76 264 printf("\r\n");
Just4pLeisure 1:d5452e398b76 265 printf("r - read SRAM and write it to ADAPTION.RAM file\r\n");
Just4pLeisure 1:d5452e398b76 266 printf("s - read Symbol Table and write it to SYMBOLS.TXT\r\n");
Just4pLeisure 1:d5452e398b76 267 printf("v - read T5 ECU software version, display it and write it to VERSION.TXT\r\n");
Just4pLeisure 1:d5452e398b76 268 printf("\r\n");
Just4pLeisure 1:d5452e398b76 269 printf("'ESC' - Return to Just4Trionic Main Menu\r\n");
Just4pLeisure 1:d5452e398b76 270 printf("\r\n");
Just4pLeisure 1:d5452e398b76 271 printf("h - Show this help menu\r\n");
Just4pLeisure 1:d5452e398b76 272 printf("\r\n");
Just4pLeisure 1:d5452e398b76 273 return;
Just4pLeisure 1:d5452e398b76 274 }
Just4pLeisure 1:d5452e398b76 275 //
Just4pLeisure 1:d5452e398b76 276 // t5_can_show_full_help
Just4pLeisure 1:d5452e398b76 277 //
Just4pLeisure 1:d5452e398b76 278 // Displays a complete list of things that can be done with the T5 ECU.
Just4pLeisure 1:d5452e398b76 279 //
Just4pLeisure 1:d5452e398b76 280 // inputs: none
Just4pLeisure 1:d5452e398b76 281 // return: none
Just4pLeisure 1:d5452e398b76 282 //
Just4pLeisure 5:1775b4b13232 283 void t5_can_show_full_help()
Just4pLeisure 5:1775b4b13232 284 {
Just4pLeisure 1:d5452e398b76 285 printf("Trionic 5 Command Menu\r\n");
Just4pLeisure 1:d5452e398b76 286 printf("======================\r\n");
Just4pLeisure 5:1775b4b13232 287 printf("D - DUMP the T5.x ECU FLASH to a file 'ORIGINAL.BIN'\r\n");
Just4pLeisure 5:1775b4b13232 288 printf("F - FLASH the update file 'MODIFIED.BIN' to the T5.x\r\n");
Just4pLeisure 1:d5452e398b76 289 printf("\r\n");
Just4pLeisure 1:d5452e398b76 290 printf("b - upload and start MyBooty.S19 bootloader\r\n");
Just4pLeisure 1:d5452e398b76 291 printf("c - get T5 ECU FLASH checksum (need to upload BOOTY.S19 before using this command)\r\n");
Just4pLeisure 1:d5452e398b76 292 printf("d - dump the T5 FLASH BIN file and write it to ORIGINAL.BIN\r\n");
Just4pLeisure 1:d5452e398b76 293 printf("e - erase the FLASH chips in the T5 ECU\r\n");
Just4pLeisure 5:1775b4b13232 294 printf("f - FLASH the update file MODIFIED.BIN to the T5 ECU\r\n");
Just4pLeisure 1:d5452e398b76 295 printf("r - read SRAM and write it to ADAPTION.RAM file\r\n");
Just4pLeisure 1:d5452e398b76 296 printf("s - read Symbol Table, display it and write it to SYMBOLS.TXT\r\n");
Just4pLeisure 1:d5452e398b76 297 printf("v - read T5 ECU software version, display it and write it to VERSION.TXT\r\n");
Just4pLeisure 1:d5452e398b76 298 printf("q - exit the bootloader and reset the T5 ECU\r\n");
Just4pLeisure 1:d5452e398b76 299 printf("t - read the FLASH chip type in the T5 ECU\r\n");
Just4pLeisure 1:d5452e398b76 300 printf("3 - read the last used FLASH address in the T5 ECU\r\n");
Just4pLeisure 1:d5452e398b76 301 printf("S - send 's' message (to get symbol table)\r\n");
Just4pLeisure 1:d5452e398b76 302 printf("V - send 'S' message (to get software version)\r\n");
Just4pLeisure 1:d5452e398b76 303 printf("'Enter' Key - send an CR message\r\n");
Just4pLeisure 1:d5452e398b76 304 printf("a - send an ACK\r\n");
Just4pLeisure 1:d5452e398b76 305 printf("A - read a single symbol from the symbol table\r\n");
Just4pLeisure 1:d5452e398b76 306 printf("\r\n");
Just4pLeisure 1:d5452e398b76 307 printf("'ESC' - Return to Just4Trionic Main Menu\r\n");
Just4pLeisure 1:d5452e398b76 308 printf("\r\n");
Just4pLeisure 1:d5452e398b76 309 printf("H - Show this help menu\r\n");
Just4pLeisure 1:d5452e398b76 310 printf("\r\n");
Just4pLeisure 1:d5452e398b76 311 return;
Just4pLeisure 1:d5452e398b76 312 }
Just4pLeisure 1:d5452e398b76 313
Just4pLeisure 1:d5452e398b76 314 //
Just4pLeisure 1:d5452e398b76 315 // t5_can_show_can_message
Just4pLeisure 1:d5452e398b76 316 //
Just4pLeisure 1:d5452e398b76 317 // Displays a CAN message in the RX buffer if there is one.
Just4pLeisure 1:d5452e398b76 318 //
Just4pLeisure 1:d5452e398b76 319 // inputs: none
Just4pLeisure 1:d5452e398b76 320 // return: bool TRUE if there was a message, FALSE if no message.
Just4pLeisure 1:d5452e398b76 321 //
Just4pLeisure 5:1775b4b13232 322 bool t5_can_show_can_message()
Just4pLeisure 5:1775b4b13232 323 {
Just4pLeisure 1:d5452e398b76 324 CANMessage can_MsgRx;
Just4pLeisure 1:d5452e398b76 325 if (can.read(can_MsgRx)) {
Just4pLeisure 1:d5452e398b76 326 printf("w%03x%d", can_MsgRx.id, can_MsgRx.len);
Just4pLeisure 1:d5452e398b76 327 for (char i=0; i<can_MsgRx.len; i++) {
Just4pLeisure 1:d5452e398b76 328 printf("%02x", can_MsgRx.data[i]);
Just4pLeisure 1:d5452e398b76 329 }
Just4pLeisure 1:d5452e398b76 330 printf(" %c ", can_MsgRx.data[2]);
Just4pLeisure 1:d5452e398b76 331 printf("\r\n");
Just4pLeisure 1:d5452e398b76 332 return TRUE;
Just4pLeisure 1:d5452e398b76 333 }
Just4pLeisure 1:d5452e398b76 334 return FALSE;
Just4pLeisure 1:d5452e398b76 335 }
Just4pLeisure 1:d5452e398b76 336
Just4pLeisure 1:d5452e398b76 337 //
Just4pLeisure 1:d5452e398b76 338 // t5_can_get_symbol_table
Just4pLeisure 1:d5452e398b76 339 //
Just4pLeisure 1:d5452e398b76 340 // Gets the T5 ECU symbol table.
Just4pLeisure 1:d5452e398b76 341 // The Symbol Table is saved to a file, symbols.txt, on the mbed 'local' file system 'disk'.
Just4pLeisure 1:d5452e398b76 342 //
Just4pLeisure 1:d5452e398b76 343 // inputs: none
Just4pLeisure 1:d5452e398b76 344 // return: bool TRUE if there all went OK, FALSE if there was an error
Just4pLeisure 1:d5452e398b76 345 //
Just4pLeisure 5:1775b4b13232 346 bool t5_can_get_symbol_table()
Just4pLeisure 5:1775b4b13232 347 {
Just4pLeisure 1:d5452e398b76 348 printf("Saving the symbol table file\r\n");
Just4pLeisure 1:d5452e398b76 349 FILE *fp = fopen("/local/symbols.txt", "w"); // Open "symbols.txt" on the local file system for writing
Just4pLeisure 1:d5452e398b76 350 if (!fp) {
Just4pLeisure 1:d5452e398b76 351 perror ("The following error occured");
Just4pLeisure 1:d5452e398b76 352 return FALSE;
Just4pLeisure 1:d5452e398b76 353 }
Just4pLeisure 1:d5452e398b76 354 char symbol[40];
Just4pLeisure 1:d5452e398b76 355 T5ReadCmnd(T5SYMBOLS);
Just4pLeisure 1:d5452e398b76 356 if (T5WaitResponse() != '>') {
Just4pLeisure 1:d5452e398b76 357 fclose(fp);
Just4pLeisure 1:d5452e398b76 358 return FALSE;
Just4pLeisure 1:d5452e398b76 359 }
Just4pLeisure 1:d5452e398b76 360 T5ReadCmnd(CR);
Just4pLeisure 1:d5452e398b76 361 if (T5WaitResponse() != '>') {
Just4pLeisure 1:d5452e398b76 362 fclose(fp);
Just4pLeisure 1:d5452e398b76 363 return FALSE;
Just4pLeisure 1:d5452e398b76 364 }
Just4pLeisure 1:d5452e398b76 365 do {
Just4pLeisure 1:d5452e398b76 366 T5GetSymbol(symbol);
Just4pLeisure 1:d5452e398b76 367 // printf("%s",symbol);
Just4pLeisure 1:d5452e398b76 368 if (fprintf(fp,"%s",symbol) < 0) {
Just4pLeisure 1:d5452e398b76 369 fclose (fp);
Just4pLeisure 1:d5452e398b76 370 printf ("ERROR Writing to the symbols.txt file!\r\n");
Just4pLeisure 1:d5452e398b76 371 return FALSE;
Just4pLeisure 1:d5452e398b76 372 };
Just4pLeisure 1:d5452e398b76 373 } while (!StrCmp(symbol,"END\r\n"));
Just4pLeisure 1:d5452e398b76 374 fclose(fp);
Just4pLeisure 1:d5452e398b76 375 return TRUE;
Just4pLeisure 1:d5452e398b76 376 }
Just4pLeisure 1:d5452e398b76 377
Just4pLeisure 1:d5452e398b76 378 //
Just4pLeisure 1:d5452e398b76 379 // t5_can_get_version
Just4pLeisure 1:d5452e398b76 380 //
Just4pLeisure 1:d5452e398b76 381 // Gets the T5 software version string.
Just4pLeisure 1:d5452e398b76 382 // The software version is is sent to the PC and saved to a file, version.txt, on the mbed 'local' file system 'disk'.
Just4pLeisure 1:d5452e398b76 383 //
Just4pLeisure 1:d5452e398b76 384 // inputs: none
Just4pLeisure 1:d5452e398b76 385 // return: bool TRUE if there all went OK, FALSE if there was an error
Just4pLeisure 1:d5452e398b76 386 //
Just4pLeisure 5:1775b4b13232 387 bool t5_can_get_version()
Just4pLeisure 5:1775b4b13232 388 {
Just4pLeisure 1:d5452e398b76 389 FILE *fp = fopen("/local/version.txt", "w"); // Open "version.txt" on the local file system for writing
Just4pLeisure 1:d5452e398b76 390 if (!fp) {
Just4pLeisure 1:d5452e398b76 391 perror ("The following error occured");
Just4pLeisure 1:d5452e398b76 392 return FALSE;
Just4pLeisure 1:d5452e398b76 393 }
Just4pLeisure 1:d5452e398b76 394 char symbol[40];
Just4pLeisure 1:d5452e398b76 395 T5ReadCmnd(T5VERSION);
Just4pLeisure 1:d5452e398b76 396 if (T5WaitResponse() != '>') {
Just4pLeisure 1:d5452e398b76 397 fclose(fp);
Just4pLeisure 1:d5452e398b76 398 return FALSE;
Just4pLeisure 1:d5452e398b76 399 }
Just4pLeisure 1:d5452e398b76 400 T5ReadCmnd(CR);
Just4pLeisure 1:d5452e398b76 401 if (T5WaitResponse() != '>') {
Just4pLeisure 1:d5452e398b76 402 fclose(fp);
Just4pLeisure 1:d5452e398b76 403 return FALSE;
Just4pLeisure 1:d5452e398b76 404 }
Just4pLeisure 1:d5452e398b76 405 T5GetSymbol(symbol);
Just4pLeisure 1:d5452e398b76 406 printf("%s",symbol);
Just4pLeisure 1:d5452e398b76 407 if (fprintf(fp,"%s",symbol) < 0) {
Just4pLeisure 1:d5452e398b76 408 fclose (fp);
Just4pLeisure 1:d5452e398b76 409 printf ("ERROR Writing to the version.txt file!\r\n");
Just4pLeisure 1:d5452e398b76 410 return FALSE;
Just4pLeisure 1:d5452e398b76 411 };
Just4pLeisure 1:d5452e398b76 412 fclose(fp);
Just4pLeisure 1:d5452e398b76 413 printf("The version.txt file has been saved.\r\n");
Just4pLeisure 1:d5452e398b76 414 return TRUE;
Just4pLeisure 1:d5452e398b76 415 }
Just4pLeisure 1:d5452e398b76 416
Just4pLeisure 1:d5452e398b76 417 //
Just4pLeisure 1:d5452e398b76 418 // Trionic5GetAdaptionData
Just4pLeisure 1:d5452e398b76 419 //
Just4pLeisure 1:d5452e398b76 420 // Gets the adaption data from the T5's SRAM.
Just4pLeisure 1:d5452e398b76 421 // The adaption data is stored in a hex file, adaption.RAM, on the mbed 'local' file system 'disk'.
Just4pLeisure 1:d5452e398b76 422 //
Just4pLeisure 1:d5452e398b76 423 // Reading the Adaption data from SRAM takes about 6.5 seconds.
Just4pLeisure 1:d5452e398b76 424 //
Just4pLeisure 1:d5452e398b76 425 // inputs: none
Just4pLeisure 1:d5452e398b76 426 // return: bool TRUE if all went OK, FALSE if there was an error.
Just4pLeisure 1:d5452e398b76 427 //
Just4pLeisure 5:1775b4b13232 428 bool t5_can_get_adaption_data()
Just4pLeisure 5:1775b4b13232 429 {
Just4pLeisure 1:d5452e398b76 430 printf("Saving the SRAM adaption data.\r\n");
Just4pLeisure 1:d5452e398b76 431 FILE *fp = fopen("/local/adaption.RAM", "w"); // Open "adaption.RAM" on the local file system for writing
Just4pLeisure 1:d5452e398b76 432 if (!fp) {
Just4pLeisure 1:d5452e398b76 433 printf("ERROR: Unable to open a file for the adaption data!\r\n");
Just4pLeisure 1:d5452e398b76 434 return FALSE;
Just4pLeisure 1:d5452e398b76 435 }
Just4pLeisure 1:d5452e398b76 436 unsigned int address = 5; // Mysterious reason for starting at 5 !!!
Just4pLeisure 1:d5452e398b76 437 char RAMdata[6];
Just4pLeisure 1:d5452e398b76 438 while (address < T5RAMSIZE) {
Just4pLeisure 1:d5452e398b76 439 if (!t5_can_read_data(RAMdata, address)) {
Just4pLeisure 1:d5452e398b76 440 fclose (fp);
Just4pLeisure 1:d5452e398b76 441 printf ("Error reading from the CAN bus.\r\n");
Just4pLeisure 1:d5452e398b76 442 return FALSE;
Just4pLeisure 1:d5452e398b76 443 }
Just4pLeisure 1:d5452e398b76 444 address += 6;
Just4pLeisure 1:d5452e398b76 445 if (fwrite(RAMdata, 1, 6, fp) != 6) {
Just4pLeisure 1:d5452e398b76 446 fclose (fp);
Just4pLeisure 1:d5452e398b76 447 printf ("Error writing to the SRAM adaption file.\r\n");
Just4pLeisure 1:d5452e398b76 448 return FALSE;
Just4pLeisure 1:d5452e398b76 449 }
Just4pLeisure 1:d5452e398b76 450 }
Just4pLeisure 1:d5452e398b76 451 // There are a few more bytes to get because because the SRAM file is not an exact multiple of 6 bytes!
Just4pLeisure 1:d5452e398b76 452 // the % (modulo) mathematics function tells us how many bytes there are still to get
Just4pLeisure 1:d5452e398b76 453 if (!t5_can_read_data(RAMdata, (T5RAMSIZE - 1))) {
Just4pLeisure 1:d5452e398b76 454 fclose (fp);
Just4pLeisure 1:d5452e398b76 455 printf ("Error reading from the CAN bus.\r\n");
Just4pLeisure 1:d5452e398b76 456 return FALSE;
Just4pLeisure 1:d5452e398b76 457 }
Just4pLeisure 1:d5452e398b76 458 if (fwrite((RAMdata + 6 - (T5RAMSIZE % 6)), 1, (T5RAMSIZE % 6), fp) != (T5RAMSIZE % 6)) {
Just4pLeisure 1:d5452e398b76 459 fclose (fp);
Just4pLeisure 1:d5452e398b76 460 printf ("Error writing to the SRAM adaption file.\r\n");
Just4pLeisure 1:d5452e398b76 461 return FALSE;
Just4pLeisure 1:d5452e398b76 462 }
Just4pLeisure 1:d5452e398b76 463 fclose(fp);
Just4pLeisure 1:d5452e398b76 464 return TRUE;
Just4pLeisure 1:d5452e398b76 465 }
Just4pLeisure 1:d5452e398b76 466
Just4pLeisure 1:d5452e398b76 467 //
Just4pLeisure 1:d5452e398b76 468 // t5_can_send_boot_loader
Just4pLeisure 1:d5452e398b76 469 //
Just4pLeisure 1:d5452e398b76 470 // Sends a 'bootloader' file, booty.s19 to the T5 ECU.
Just4pLeisure 1:d5452e398b76 471 // The 'bootloader' is stored on the mbed 'local' file system 'disk' and must be in S19 format.
Just4pLeisure 1:d5452e398b76 472 //
Just4pLeisure 1:d5452e398b76 473 // The 'bootloader' is then able to dump or reFLASH the T5 ECU FLASH chips - this is the whole point of the exercise :-)
Just4pLeisure 1:d5452e398b76 474 //
Just4pLeisure 1:d5452e398b76 475 // Sending the 'bootloader' to the T5 ECU takes just over 1 second.
Just4pLeisure 1:d5452e398b76 476 //
Just4pLeisure 1:d5452e398b76 477 // inputs: none
Just4pLeisure 1:d5452e398b76 478 // return: bool TRUE if all went OK,
Just4pLeisure 1:d5452e398b76 479 // FALSE if the 'bootloader' wasn't sent for some reason.
Just4pLeisure 1:d5452e398b76 480 //
Just4pLeisure 5:1775b4b13232 481 bool t5_can_send_boot_loader()
Just4pLeisure 5:1775b4b13232 482 {
Just4pLeisure 5:1775b4b13232 483 uint32_t BootloaderSize = sizeof(T5BootLoader);
Just4pLeisure 5:1775b4b13232 484 uint32_t address = MYBOOTY_START; // Start and execute from address of T5Bootloader
Just4pLeisure 5:1775b4b13232 485 uint32_t count = 0; // progress count of bootloader bytes transferred
Just4pLeisure 5:1775b4b13232 486 char msg[8]; // Construct the bootloader frame for uploading
Just4pLeisure 5:1775b4b13232 487
Just4pLeisure 5:1775b4b13232 488 printf("Starting the bootloader.\r\n");
Just4pLeisure 5:1775b4b13232 489 while (count < BootloaderSize) {
Just4pLeisure 5:1775b4b13232 490 // send a bootloader address message
Just4pLeisure 5:1775b4b13232 491 if (!t5_can_send_boot_address((address+count), MYBOOTY_CHUNK)) return FALSE;
Just4pLeisure 5:1775b4b13232 492 // send bootloader frames
Just4pLeisure 5:1775b4b13232 493 // 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 5:1775b4b13232 494 // 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 5:1775b4b13232 495 // is sent with the upload address) and ignores any extra bytes in the last frame.
Just4pLeisure 5:1775b4b13232 496 for (uint8_t i=0; i<MYBOOTY_CHUNK; i++) {
Just4pLeisure 5:1775b4b13232 497 msg[1+(i%7)] = T5BootLoader[count+i];
Just4pLeisure 5:1775b4b13232 498 if (i%7 == 0) msg[0]=i; // set the index number
Just4pLeisure 5:1775b4b13232 499 if ((i%7 == 6) || (i == MYBOOTY_CHUNK-1 )) {
Just4pLeisure 5:1775b4b13232 500 if (!t5_can_send_boot_frame(msg)) return FALSE;
Just4pLeisure 5:1775b4b13232 501 }
Just4pLeisure 5:1775b4b13232 502 }
Just4pLeisure 5:1775b4b13232 503 count += MYBOOTY_CHUNK;
Just4pLeisure 5:1775b4b13232 504 }
Just4pLeisure 5:1775b4b13232 505 // These two lines really shouldn't be necessary but for some reason the first start
Just4pLeisure 5:1775b4b13232 506 // command is ignored and a short delay is required before repeating. Using only a
Just4pLeisure 5:1775b4b13232 507 // delay, even a very long one, doesn't work.
Just4pLeisure 5:1775b4b13232 508 //
Just4pLeisure 5:1775b4b13232 509 // NOTE: This measure isn't required when uploading an external S19 bootloader file!
Just4pLeisure 5:1775b4b13232 510 //
Just4pLeisure 5:1775b4b13232 511 T5StartBootLoader(address);
Just4pLeisure 5:1775b4b13232 512 wait_ms(1);
Just4pLeisure 5:1775b4b13232 513 //
Just4pLeisure 5:1775b4b13232 514 return T5StartBootLoader(address);
Just4pLeisure 5:1775b4b13232 515 }
Just4pLeisure 5:1775b4b13232 516
Just4pLeisure 5:1775b4b13232 517
Just4pLeisure 5:1775b4b13232 518 //
Just4pLeisure 5:1775b4b13232 519 // t5_can_send_boot_loader_S19
Just4pLeisure 5:1775b4b13232 520 //
Just4pLeisure 5:1775b4b13232 521 // Sends a 'bootloader' file, booty.s19 to the T5 ECU.
Just4pLeisure 5:1775b4b13232 522 // The 'bootloader' is stored on the mbed 'local' file system 'disk' and must be in S19 format.
Just4pLeisure 5:1775b4b13232 523 //
Just4pLeisure 5:1775b4b13232 524 // The 'bootloader' is then able to dump or reFLASH the T5 ECU FLASH chips - this is the whole point of the exercise :-)
Just4pLeisure 5:1775b4b13232 525 //
Just4pLeisure 5:1775b4b13232 526 // Sending the 'bootloader' to the T5 ECU takes just over 1 second.
Just4pLeisure 5:1775b4b13232 527 //
Just4pLeisure 5:1775b4b13232 528 // inputs: none
Just4pLeisure 5:1775b4b13232 529 // return: bool TRUE if all went OK,
Just4pLeisure 5:1775b4b13232 530 // FALSE if the 'bootloader' wasn't sent for some reason.
Just4pLeisure 5:1775b4b13232 531 //
Just4pLeisure 5:1775b4b13232 532 bool t5_can_send_boot_loader_S19()
Just4pLeisure 5:1775b4b13232 533 {
Just4pLeisure 1:d5452e398b76 534 printf("Starting the bootloader.\r\n");
Just4pLeisure 1:d5452e398b76 535 FILE *fp = fopen("/local/MyBooty.S19", "r"); // Open "booty.s19" on the local file system for reading
Just4pLeisure 1:d5452e398b76 536 if (!fp) {
Just4pLeisure 1:d5452e398b76 537 printf("Error: I could not find the bootloader file MyBooty.S19\r\n");
Just4pLeisure 1:d5452e398b76 538 return FALSE;
Just4pLeisure 1:d5452e398b76 539 }
Just4pLeisure 1:d5452e398b76 540 int c = 0; // for some reason fgetc returns an int instead of a char
Just4pLeisure 1:d5452e398b76 541 uint8_t count = 0; // count of bytes in the S-record can be 0xFF = 255 in decimal
Just4pLeisure 1:d5452e398b76 542 uint8_t asize = 0; // 2,3 or 4 bytes in address
Just4pLeisure 1:d5452e398b76 543 uint32_t address = 0; // address to put S-record
Just4pLeisure 1:d5452e398b76 544 uint8_t checksum = 0; // checksum check at the end of each S-record line
Just4pLeisure 1:d5452e398b76 545 char msg[8]; // Construct the bootloader frame for uploading
Just4pLeisure 1:d5452e398b76 546 bool sent = FALSE;
Just4pLeisure 1:d5452e398b76 547
Just4pLeisure 1:d5452e398b76 548 while (!sent) {
Just4pLeisure 1:d5452e398b76 549 // get characters until we get an 'S' (throws away \n,\r characters and other junk)
Just4pLeisure 1:d5452e398b76 550 do c = fgetc (fp);
Just4pLeisure 1:d5452e398b76 551 while (c != 'S' && c != EOF);
Just4pLeisure 1:d5452e398b76 552 // if (c == EOF) return '\a';
Just4pLeisure 1:d5452e398b76 553 c = fgetc(fp); // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached)
Just4pLeisure 1:d5452e398b76 554 // if ((c = fgetc(fp)) == EOF) return '\a'; // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached)
Just4pLeisure 1:d5452e398b76 555 switch (c) {
Just4pLeisure 1:d5452e398b76 556 case '0':
Just4pLeisure 1:d5452e398b76 557 break; // Skip over S0 header record
Just4pLeisure 1:d5452e398b76 558
Just4pLeisure 1:d5452e398b76 559 case '1':
Just4pLeisure 1:d5452e398b76 560 case '2':
Just4pLeisure 1:d5452e398b76 561 case '3':
Just4pLeisure 1:d5452e398b76 562 asize = 1 + c - '0'; // 2, 3 or 4 bytes for address
Just4pLeisure 1:d5452e398b76 563 address = 0;
Just4pLeisure 1:d5452e398b76 564 // get the number of bytes (in ascii format) in this S-record line
Just4pLeisure 1:d5452e398b76 565 // there must be at least the address and the checksum so return with an error if less than this!
Just4pLeisure 1:d5452e398b76 566 if ((c = SRecGetByte(fp)) < (asize + 1)) break;
Just4pLeisure 1:d5452e398b76 567 // if ((c = SRecGetByte(fp)) < 3) return '\a';
Just4pLeisure 1:d5452e398b76 568 count = c;
Just4pLeisure 1:d5452e398b76 569 checksum = c;
Just4pLeisure 1:d5452e398b76 570 // get the address
Just4pLeisure 1:d5452e398b76 571 for (uint8_t i=0; i<asize; i++) {
Just4pLeisure 1:d5452e398b76 572 c = SRecGetByte(fp);
Just4pLeisure 1:d5452e398b76 573 checksum += c;
Just4pLeisure 1:d5452e398b76 574 address <<= 8;
Just4pLeisure 1:d5452e398b76 575 address |= c;
Just4pLeisure 1:d5452e398b76 576 count--;
Just4pLeisure 1:d5452e398b76 577 }
Just4pLeisure 1:d5452e398b76 578 // send a bootloader address message
Just4pLeisure 5:1775b4b13232 579 //// printf("address %x count %x\r\n",address ,count-1 );
Just4pLeisure 1:d5452e398b76 580 if (!t5_can_send_boot_address(address, (count-1))) return FALSE;
Just4pLeisure 1:d5452e398b76 581 // get and send the bootloader frames for this S-record
Just4pLeisure 1:d5452e398b76 582 // 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 1:d5452e398b76 583 // 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 1:d5452e398b76 584 // in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame.
Just4pLeisure 1:d5452e398b76 585 for (uint8_t i=0; i<count-1; i++) {
Just4pLeisure 1:d5452e398b76 586 c = SRecGetByte(fp);
Just4pLeisure 1:d5452e398b76 587 checksum += c;
Just4pLeisure 1:d5452e398b76 588 msg[1+(i%7)] = c;
Just4pLeisure 1:d5452e398b76 589 if (i%7 == 0) msg[0]=i; // set the index number
Just4pLeisure 5:1775b4b13232 590 if ((i%7 == 6) || (i == count - 2)) {
Just4pLeisure 5:1775b4b13232 591 //// 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] );
Just4pLeisure 1:d5452e398b76 592 if (!t5_can_send_boot_frame(msg)) {
Just4pLeisure 1:d5452e398b76 593 fclose(fp);
Just4pLeisure 1:d5452e398b76 594 return FALSE;
Just4pLeisure 1:d5452e398b76 595 }
Just4pLeisure 5:1775b4b13232 596 }
Just4pLeisure 1:d5452e398b76 597 }
Just4pLeisure 1:d5452e398b76 598 // get the checksum
Just4pLeisure 1:d5452e398b76 599 if ((checksum += SRecGetByte(fp)) != 0xFF) {
Just4pLeisure 1:d5452e398b76 600 printf("Error in S-record, checksum = %2x\r\n", checksum);
Just4pLeisure 1:d5452e398b76 601 fclose(fp);
Just4pLeisure 1:d5452e398b76 602 return FALSE;
Just4pLeisure 1:d5452e398b76 603 }
Just4pLeisure 1:d5452e398b76 604 break;
Just4pLeisure 1:d5452e398b76 605
Just4pLeisure 1:d5452e398b76 606 case '5':
Just4pLeisure 1:d5452e398b76 607 break; // Skip over S5 record types
Just4pLeisure 1:d5452e398b76 608
Just4pLeisure 1:d5452e398b76 609 case '7':
Just4pLeisure 1:d5452e398b76 610 case '8':
Just4pLeisure 1:d5452e398b76 611 case '9':
Just4pLeisure 1:d5452e398b76 612 asize = 11 - (c - '0'); // 2, 3 or 4 bytes for address
Just4pLeisure 5:1775b4b13232 613 address = 0;
Just4pLeisure 1:d5452e398b76 614 // get the number of bytes (in ascii format) in this S-record line there must be just the address and the checksum
Just4pLeisure 1:d5452e398b76 615 // so return with an error if other than this!
Just4pLeisure 1:d5452e398b76 616 if ((c = SRecGetByte(fp)) != (asize + 1)) break;
Just4pLeisure 1:d5452e398b76 617 // if ((c = SRecGetByte(fp)) < 3) return '\a';
Just4pLeisure 1:d5452e398b76 618 checksum = c;
Just4pLeisure 1:d5452e398b76 619 // get the address
Just4pLeisure 1:d5452e398b76 620 for (uint8_t i=0; i<asize; i++) {
Just4pLeisure 1:d5452e398b76 621 c = SRecGetByte(fp);
Just4pLeisure 1:d5452e398b76 622 checksum += c;
Just4pLeisure 1:d5452e398b76 623 address <<= 8;
Just4pLeisure 1:d5452e398b76 624 address |= c;
Just4pLeisure 1:d5452e398b76 625 }
Just4pLeisure 1:d5452e398b76 626 // get the checksum
Just4pLeisure 1:d5452e398b76 627 if ((checksum += SRecGetByte(fp)) != 0xFF) {
Just4pLeisure 1:d5452e398b76 628 fclose(fp);
Just4pLeisure 1:d5452e398b76 629 printf("Error in S-record, checksum = %2x\r\n", checksum);
Just4pLeisure 1:d5452e398b76 630 return FALSE;
Just4pLeisure 1:d5452e398b76 631 }
Just4pLeisure 1:d5452e398b76 632 T5StartBootLoader(address);
Just4pLeisure 1:d5452e398b76 633 // T5WaitResponsePrint();
Just4pLeisure 1:d5452e398b76 634 sent = TRUE;
Just4pLeisure 1:d5452e398b76 635 break;
Just4pLeisure 1:d5452e398b76 636
Just4pLeisure 1:d5452e398b76 637 // Some kind of invalid S-record type so break
Just4pLeisure 1:d5452e398b76 638 default:
Just4pLeisure 1:d5452e398b76 639 fclose(fp);
Just4pLeisure 1:d5452e398b76 640 printf("oops - didn't recognise that S-Record \r\n");
Just4pLeisure 1:d5452e398b76 641 return FALSE;
Just4pLeisure 1:d5452e398b76 642 }
Just4pLeisure 1:d5452e398b76 643 }
Just4pLeisure 1:d5452e398b76 644 fclose(fp);
Just4pLeisure 1:d5452e398b76 645 return TRUE;
Just4pLeisure 1:d5452e398b76 646 }
Just4pLeisure 1:d5452e398b76 647
Just4pLeisure 1:d5452e398b76 648 //
Just4pLeisure 1:d5452e398b76 649 // t5_can_get_checksum
Just4pLeisure 1:d5452e398b76 650 //
Just4pLeisure 1:d5452e398b76 651 // Calculates the checksum of the FLASH in the T5 ECU.
Just4pLeisure 1:d5452e398b76 652 // The 'bootloader', booty.s19, must be loaded before this function can be used.
Just4pLeisure 1:d5452e398b76 653 // The 'bootloader' actually calculates the checksum and compares it with the
Just4pLeisure 1:d5452e398b76 654 // value stored in the 'header' region at the end of the FLASH.
Just4pLeisure 1:d5452e398b76 655 //
Just4pLeisure 1:d5452e398b76 656 // The bootloader sends a single CAN message with the result e.g.
Just4pLeisure 1:d5452e398b76 657 // w00C8C800CAFEBABE0808
Just4pLeisure 1:d5452e398b76 658 // 00C - T5 response messages have an CAN id of 00C
Just4pLeisure 1:d5452e398b76 659 // 8 - All T5 messages have a message length of 8 bytes
Just4pLeisure 1:d5452e398b76 660 // C8 - This is the checksum message type
Just4pLeisure 1:d5452e398b76 661 // 00 - 00 means OK, the checksum calculation matches the stored value which in this case is:
Just4pLeisure 1:d5452e398b76 662 // CAFEBABE - lol :-)
Just4pLeisure 1:d5452e398b76 663 //
Just4pLeisure 1:d5452e398b76 664 // w00C8C801FFFFFFFF0808
Just4pLeisure 1:d5452e398b76 665 // 01 - 01 means calculated value doesn't matched the stored value
Just4pLeisure 1:d5452e398b76 666 // FFFFFFFF - in this case the stored value is FFFFFFFF - the chips might be erased
Just4pLeisure 1:d5452e398b76 667 //
Just4pLeisure 1:d5452e398b76 668 // Calculating the checksum takes a little under 2 seconds.
Just4pLeisure 1:d5452e398b76 669 //
Just4pLeisure 1:d5452e398b76 670 // inputs: none
Just4pLeisure 1:d5452e398b76 671 // return: bool TRUE if all went OK,
Just4pLeisure 1:d5452e398b76 672 //
Just4pLeisure 5:1775b4b13232 673 bool t5_can_get_checksum()
Just4pLeisure 5:1775b4b13232 674 {
Just4pLeisure 1:d5452e398b76 675 uint32_t checksum = 0;
Just4pLeisure 1:d5452e398b76 676 if (!t5_boot_checksum_command(&checksum)) {
Just4pLeisure 1:d5452e398b76 677 printf("Error The ECU's checksum is wrong!\r\n");
Just4pLeisure 1:d5452e398b76 678 return FALSE;
Just4pLeisure 1:d5452e398b76 679 }
Just4pLeisure 1:d5452e398b76 680 printf("The FLASH checksum value is %#010x.\r\n", checksum);
Just4pLeisure 1:d5452e398b76 681 return TRUE;
Just4pLeisure 1:d5452e398b76 682 }
Just4pLeisure 1:d5452e398b76 683
Just4pLeisure 1:d5452e398b76 684 //
Just4pLeisure 1:d5452e398b76 685 // t5_can_bootloader_reset
Just4pLeisure 1:d5452e398b76 686 //
Just4pLeisure 1:d5452e398b76 687 // Exit the Bootloader and restart the T5 ECU
Just4pLeisure 1:d5452e398b76 688 //
Just4pLeisure 1:d5452e398b76 689 // inputs: none
Just4pLeisure 1:d5452e398b76 690 // outputs: bool TRUE if all went OK.
Just4pLeisure 1:d5452e398b76 691 //
Just4pLeisure 5:1775b4b13232 692 bool t5_can_bootloader_reset()
Just4pLeisure 5:1775b4b13232 693 {
Just4pLeisure 1:d5452e398b76 694 printf("Exiting the bootloader and restarting the T5 ECU.\r\n");
Just4pLeisure 1:d5452e398b76 695 if (!t5_boot_reset_command()) {
Just4pLeisure 1:d5452e398b76 696 printf("Error trying to reset the T5 ECU!\r\n");
Just4pLeisure 1:d5452e398b76 697 return FALSE;
Just4pLeisure 1:d5452e398b76 698 }
Just4pLeisure 1:d5452e398b76 699 return TRUE;
Just4pLeisure 1:d5452e398b76 700 }
Just4pLeisure 1:d5452e398b76 701
Just4pLeisure 1:d5452e398b76 702 //
Just4pLeisure 1:d5452e398b76 703 // t5_can_get_start_and_chip_types
Just4pLeisure 1:d5452e398b76 704 //
Just4pLeisure 1:d5452e398b76 705 // Gets the FLASH chip type fitted.
Just4pLeisure 1:d5452e398b76 706 //
Just4pLeisure 1:d5452e398b76 707 // NOTE the bootloader must be loaded in order to use this function.
Just4pLeisure 1:d5452e398b76 708 //
Just4pLeisure 1:d5452e398b76 709 // CAN messages from the T5 ECU with FLASH data look like this:
Just4pLeisure 1:d5452e398b76 710 //
Just4pLeisure 1:d5452e398b76 711 // C9,00,aa,aa,aa,aa,mm,dd,
Just4pLeisure 1:d5452e398b76 712 //
Just4pLeisure 1:d5452e398b76 713 // C9 lets us know its a FLASH id message
Just4pLeisure 1:d5452e398b76 714 //
Just4pLeisure 1:d5452e398b76 715 // 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 1:d5452e398b76 716 // 0x00020000 - T5.2
Just4pLeisure 1:d5452e398b76 717 // 0x00040000 - T5.5
Just4pLeisure 1:d5452e398b76 718 //
Just4pLeisure 1:d5452e398b76 719 // mm = Manufacturer id. These can be:
Just4pLeisure 1:d5452e398b76 720 // 0x89 - Intel
Just4pLeisure 1:d5452e398b76 721 // 0x31 - CSI/CAT
Just4pLeisure 1:d5452e398b76 722 // 0x01 - AMD
Just4pLeisure 1:d5452e398b76 723 // 0x1F - Atmel
Just4pLeisure 1:d5452e398b76 724 //
Just4pLeisure 1:d5452e398b76 725 // dd = Device id. These can be:
Just4pLeisure 1:d5452e398b76 726 // 0xB8 - Intel _or_ CSI 28F512 (Fiited by Saab in T5.2)
Just4pLeisure 1:d5452e398b76 727 // 0xB4 - Intel _or_ CSI 28F010 (Fitted by Saab in T5.5)
Just4pLeisure 1:d5452e398b76 728 // 0x25 - AMD 28F512 (Fiited by Saab in T5.2)
Just4pLeisure 1:d5452e398b76 729 // 0xA7 - AMD 28F010 (Fitted by Saab in T5.5)
Just4pLeisure 1:d5452e398b76 730 // 0x20 - AMD 29F010 (Some people have put these in their T5.5)
Just4pLeisure 1:d5452e398b76 731 // 0x5D - Atmel 29C512 (Some people mave have put these in their T5.2)
Just4pLeisure 1:d5452e398b76 732 // 0xD5 - Atmel 29C010 (Some people have put these in their T5.5)
Just4pLeisure 1:d5452e398b76 733 //
Just4pLeisure 1:d5452e398b76 734 // mm = 0xFF, dd == 0xF7 probably means that the programming voltage isn't right.
Just4pLeisure 1:d5452e398b76 735 //
Just4pLeisure 1:d5452e398b76 736 // Finding out which ECU type and FLASH chips are fitted takes under a second.
Just4pLeisure 1:d5452e398b76 737 //
Just4pLeisure 1:d5452e398b76 738 // inputs: start T5 ecu start address
Just4pLeisure 1:d5452e398b76 739 // return: bool TRUE if all went OK.
Just4pLeisure 1:d5452e398b76 740 //
Just4pLeisure 5:1775b4b13232 741 bool t5_can_get_start_and_chip_types(uint32_t* start)
Just4pLeisure 5:1775b4b13232 742 {
Just4pLeisure 1:d5452e398b76 743 *start = 0;
Just4pLeisure 1:d5452e398b76 744 uint8_t make = 0;
Just4pLeisure 1:d5452e398b76 745 uint8_t type = 0;
Just4pLeisure 1:d5452e398b76 746 if (!t5_boot_get_flash_type(start, &make, &type)) {
Just4pLeisure 1:d5452e398b76 747 printf("Error trying to find out the ECU's first address and FLASH chip type!\r\n");
Just4pLeisure 1:d5452e398b76 748 return FALSE;
Just4pLeisure 1:d5452e398b76 749 }
Just4pLeisure 1:d5452e398b76 750 printf("This is a T5.%s ECU with ", ((*start == T52FLASHSTART) ? "2" : "5"));
Just4pLeisure 1:d5452e398b76 751 switch (make) {
Just4pLeisure 1:d5452e398b76 752 case AMD:
Just4pLeisure 1:d5452e398b76 753 printf("AMD ");
Just4pLeisure 1:d5452e398b76 754 break;
Just4pLeisure 1:d5452e398b76 755 case CSI:
Just4pLeisure 1:d5452e398b76 756 printf("CSI ");
Just4pLeisure 1:d5452e398b76 757 break;
Just4pLeisure 1:d5452e398b76 758 case INTEL:
Just4pLeisure 1:d5452e398b76 759 printf("INTEL ");
Just4pLeisure 1:d5452e398b76 760 break;
Just4pLeisure 5:1775b4b13232 761 case ATMEL:
Just4pLeisure 5:1775b4b13232 762 printf("ATMEL ");
Just4pLeisure 5:1775b4b13232 763 break;
Just4pLeisure 5:1775b4b13232 764 case SST:
Just4pLeisure 5:1775b4b13232 765 printf("SST ");
Just4pLeisure 5:1775b4b13232 766 break;
Just4pLeisure 5:1775b4b13232 767 case ST:
Just4pLeisure 5:1775b4b13232 768 printf("ST ");
Just4pLeisure 5:1775b4b13232 769 break;
Just4pLeisure 5:1775b4b13232 770 case AMIC:
Just4pLeisure 5:1775b4b13232 771 printf("AMIC ");
Just4pLeisure 5:1775b4b13232 772 break;
Just4pLeisure 1:d5452e398b76 773 default:
Just4pLeisure 5:1775b4b13232 774 printf("\r\nUNKNOWN Manufacturer Id: %02x - Also check pin65 has enough volts!\r\n", make);
Just4pLeisure 1:d5452e398b76 775 }
Just4pLeisure 1:d5452e398b76 776 switch (type) {
Just4pLeisure 1:d5452e398b76 777 case AMD28F512:
Just4pLeisure 1:d5452e398b76 778 case INTEL28F512:
Just4pLeisure 1:d5452e398b76 779 printf("28F512 FLASH chips.\r\n");
Just4pLeisure 1:d5452e398b76 780 break;
Just4pLeisure 5:1775b4b13232 781 case ATMEL29C512:
Just4pLeisure 5:1775b4b13232 782 printf("29C512 FLASH chips.\r\n");
Just4pLeisure 5:1775b4b13232 783 break;
Just4pLeisure 5:1775b4b13232 784 case ATMEL29C010:
Just4pLeisure 5:1775b4b13232 785 printf("29C010 FLASH chips.\r\n");
Just4pLeisure 5:1775b4b13232 786 break;
Just4pLeisure 1:d5452e398b76 787 case AMD28F010:
Just4pLeisure 1:d5452e398b76 788 case INTEL28F010:
Just4pLeisure 1:d5452e398b76 789 printf("28F010 FLASH chips.\r\n");
Just4pLeisure 1:d5452e398b76 790 break;
Just4pLeisure 1:d5452e398b76 791 case AMD29F010:
Just4pLeisure 5:1775b4b13232 792 case SST39SF010:
Just4pLeisure 5:1775b4b13232 793 // case ST29F010: // Same as AMD29F010
Just4pLeisure 5:1775b4b13232 794 case AMICA29010L:
Just4pLeisure 1:d5452e398b76 795 printf("29F010 FLASH chips.\r\n");
Just4pLeisure 1:d5452e398b76 796 break;
Just4pLeisure 1:d5452e398b76 797 default:
Just4pLeisure 5:1775b4b13232 798 printf("UNKNOWN Device Id: %02x - Also check pin65 has enough volts!\r\n", type);
Just4pLeisure 1:d5452e398b76 799 return FALSE;
Just4pLeisure 1:d5452e398b76 800 }
Just4pLeisure 1:d5452e398b76 801 return TRUE;
Just4pLeisure 1:d5452e398b76 802 }
Just4pLeisure 1:d5452e398b76 803
Just4pLeisure 1:d5452e398b76 804 //
Just4pLeisure 1:d5452e398b76 805 // t5_can_erase_flash
Just4pLeisure 1:d5452e398b76 806 //
Just4pLeisure 1:d5452e398b76 807 // Erases the FLASH Chips.
Just4pLeisure 1:d5452e398b76 808 //
Just4pLeisure 1:d5452e398b76 809 // NOTE the bootloader must be loaded in order to use this function.
Just4pLeisure 1:d5452e398b76 810 //
Just4pLeisure 1:d5452e398b76 811 // CAN messages from the T5 ECU with FLASH erase command look like this:
Just4pLeisure 1:d5452e398b76 812 //
Just4pLeisure 1:d5452e398b76 813 // C0,cc,08,08,08,08,08,08
Just4pLeisure 1:d5452e398b76 814 //
Just4pLeisure 1:d5452e398b76 815 // C0 tells us this is a response to the FLASH erase command.
Just4pLeisure 1:d5452e398b76 816 //
Just4pLeisure 1:d5452e398b76 817 // cc is a code that tells us what happened:
Just4pLeisure 1:d5452e398b76 818 // 00 - FLASH was erased OK
Just4pLeisure 1:d5452e398b76 819 // 01 - Could not erase FLASH chips to 0xFF
Just4pLeisure 1:d5452e398b76 820 // 02 - Could not write 0x00 to 28F FLASH chips
Just4pLeisure 1:d5452e398b76 821 // 03 - Unrecognised FLASH chip type (or maybe programming voltage isn't right)
Just4pLeisure 1:d5452e398b76 822 // 04 - Intel chips found, but unrecognised type
Just4pLeisure 1:d5452e398b76 823 // 05 - AMD chips found, but unrecognised type
Just4pLeisure 1:d5452e398b76 824 // 06 - CSI/Catalyst chips found, but unrecognised type
Just4pLeisure 1:d5452e398b76 825 // 07 - Atmel chips found - Atmel chips don't need to be erased
Just4pLeisure 1:d5452e398b76 826 //
Just4pLeisure 1:d5452e398b76 827 // Erasing 28F type FLASH chips takes around 22 seconds. 29F chips take around 4 seconds.
Just4pLeisure 1:d5452e398b76 828 //
Just4pLeisure 1:d5452e398b76 829 // inputs: none
Just4pLeisure 1:d5452e398b76 830 // return: bool TRUE if all went OK.
Just4pLeisure 1:d5452e398b76 831 //
Just4pLeisure 5:1775b4b13232 832 bool t5_can_erase_flash()
Just4pLeisure 5:1775b4b13232 833 {
Just4pLeisure 1:d5452e398b76 834 printf("Erasing the FLASH chips.\r\n");
Just4pLeisure 1:d5452e398b76 835 if (!t5_boot_erase_command()) {
Just4pLeisure 1:d5452e398b76 836 printf("Error The ECU's FLASH has not been erased!\r\n");
Just4pLeisure 1:d5452e398b76 837 return FALSE;
Just4pLeisure 1:d5452e398b76 838 }
Just4pLeisure 1:d5452e398b76 839 return TRUE;
Just4pLeisure 1:d5452e398b76 840 }
Just4pLeisure 1:d5452e398b76 841
Just4pLeisure 1:d5452e398b76 842 //
Just4pLeisure 1:d5452e398b76 843 // t5_can_dump_flash
Just4pLeisure 1:d5452e398b76 844 //
Just4pLeisure 1:d5452e398b76 845 // Dumps the FLASH chip BIN file, original.bin to the mbed 'disk'
Just4pLeisure 1:d5452e398b76 846 //
Just4pLeisure 1:d5452e398b76 847 // NOTE the bootloader must be loaded in order to use this function.
Just4pLeisure 1:d5452e398b76 848 //
Just4pLeisure 1:d5452e398b76 849 // Dumping FLASH chips in a T5.5 ECU takes around 35 seconds.
Just4pLeisure 1:d5452e398b76 850 // Dumping T5.2 ECUs should take about half of this time
Just4pLeisure 1:d5452e398b76 851 //
Just4pLeisure 1:d5452e398b76 852 // inputs: start start address of the T5.x FLASH
Just4pLeisure 1:d5452e398b76 853
Just4pLeisure 1:d5452e398b76 854 // return: bool TRUE if all went OK, FALSE if there was an error.
Just4pLeisure 1:d5452e398b76 855 //
Just4pLeisure 5:1775b4b13232 856 bool t5_can_dump_flash(uint32_t start)
Just4pLeisure 5:1775b4b13232 857 {
Just4pLeisure 1:d5452e398b76 858 printf("Saving the original FLASH BIN file.\r\n");
Just4pLeisure 1:d5452e398b76 859 FILE *fp = fopen("/local/original.bin", "w"); // Open "original.bin" on the local file system for writing
Just4pLeisure 1:d5452e398b76 860 if (!fp) {
Just4pLeisure 1:d5452e398b76 861 perror ("The following error occured");
Just4pLeisure 1:d5452e398b76 862 return FALSE;
Just4pLeisure 1:d5452e398b76 863 }
Just4pLeisure 1:d5452e398b76 864 uint32_t address = start + 5; // Mysterious reason for starting at 5 !!!
Just4pLeisure 1:d5452e398b76 865 char FLASHdata[6];
Just4pLeisure 5:1775b4b13232 866 printf(" 0.00 %% complete.\r");
Just4pLeisure 1:d5452e398b76 867 while (address < TRIONICLASTADDR) {
Just4pLeisure 1:d5452e398b76 868 if (!t5_can_read_data(FLASHdata, address)) {
Just4pLeisure 1:d5452e398b76 869 fclose (fp);
Just4pLeisure 1:d5452e398b76 870 printf ("Error reading from the CAN bus.\r\n");
Just4pLeisure 1:d5452e398b76 871 return FALSE;
Just4pLeisure 1:d5452e398b76 872 }
Just4pLeisure 1:d5452e398b76 873 address += 6;
Just4pLeisure 1:d5452e398b76 874 if (fwrite(FLASHdata, 1, 6, fp) != 6) {
Just4pLeisure 1:d5452e398b76 875 fclose (fp);
Just4pLeisure 1:d5452e398b76 876 printf ("Error writing to the FLASH BIN file.\r\n");
Just4pLeisure 1:d5452e398b76 877 return FALSE;
Just4pLeisure 1:d5452e398b76 878 }
Just4pLeisure 5:1775b4b13232 879 printf("%6.2f\r", 100*(float)(address-start)/(float)(TRIONICLASTADDR - start) );
Just4pLeisure 1:d5452e398b76 880 }
Just4pLeisure 1:d5452e398b76 881 // There are a few more bytes to get because because the bin file is not an exact multiple of 6 bytes!
Just4pLeisure 1:d5452e398b76 882 // the % (modulo) mathematics function tells us how many bytes there are still to get
Just4pLeisure 1:d5452e398b76 883 if (!t5_can_read_data(FLASHdata, (TRIONICLASTADDR))) {
Just4pLeisure 1:d5452e398b76 884 fclose (fp);
Just4pLeisure 1:d5452e398b76 885 printf ("Error reading from the CAN bus.\r\n");
Just4pLeisure 1:d5452e398b76 886 return FALSE;
Just4pLeisure 1:d5452e398b76 887 }
Just4pLeisure 1:d5452e398b76 888 if (fwrite((FLASHdata + 6 - ((TRIONICLASTADDR - start +1) % 6)), 1, ((TRIONICLASTADDR - start +1) % 6), fp) != ((TRIONICLASTADDR - start +1) % 6)) {
Just4pLeisure 1:d5452e398b76 889 fclose (fp);
Just4pLeisure 1:d5452e398b76 890 printf ("Error writing to the FLASH BIN file.\r\n");
Just4pLeisure 1:d5452e398b76 891 return FALSE;
Just4pLeisure 1:d5452e398b76 892 }
Just4pLeisure 5:1775b4b13232 893 printf("100.00 %% complete.\r\n");
Just4pLeisure 1:d5452e398b76 894 fclose(fp);
Just4pLeisure 1:d5452e398b76 895 return TRUE;
Just4pLeisure 1:d5452e398b76 896 }
Just4pLeisure 1:d5452e398b76 897
Just4pLeisure 1:d5452e398b76 898
Just4pLeisure 1:d5452e398b76 899 //
Just4pLeisure 1:d5452e398b76 900 // t5_can_send_flash_bin_update
Just4pLeisure 1:d5452e398b76 901 //
Just4pLeisure 5:1775b4b13232 902 // Sends a FLASH update file, modified.bin to the T5 ECU.
Just4pLeisure 1:d5452e398b76 903 // The FLASH update file is stored on the local file system and must be in hex format.
Just4pLeisure 1:d5452e398b76 904 //
Just4pLeisure 1:d5452e398b76 905 // FLASHing a T5.5 ECU takes around 40 seconds. FLASHing T5.2 ECUs should take about half of this time
Just4pLeisure 1:d5452e398b76 906 //
Just4pLeisure 1:d5452e398b76 907 // inputs: start start address of the T5.x FLASH
Just4pLeisure 1:d5452e398b76 908
Just4pLeisure 1:d5452e398b76 909 // return: bool TRUE if all went OK,
Just4pLeisure 1:d5452e398b76 910 // FALSE if the FLASH update failed for some reason.
Just4pLeisure 1:d5452e398b76 911 //
Just4pLeisure 5:1775b4b13232 912 bool t5_can_send_flash_bin_update(uint32_t start)
Just4pLeisure 5:1775b4b13232 913 {
Just4pLeisure 1:d5452e398b76 914 printf("Programming the FLASH chips.\r\n");
Just4pLeisure 5:1775b4b13232 915 FILE *fp = fopen("/local/modified.bin", "r"); // Open "modified.bin" on the local file system for reading
Just4pLeisure 1:d5452e398b76 916 if (!fp) {
Just4pLeisure 5:1775b4b13232 917 printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");
Just4pLeisure 1:d5452e398b76 918 return FALSE;
Just4pLeisure 1:d5452e398b76 919 }
Just4pLeisure 1:d5452e398b76 920
Just4pLeisure 1:d5452e398b76 921 // obtain file size - it should match the size of the FLASH chips:
Just4pLeisure 1:d5452e398b76 922 fseek (fp , 0 , SEEK_END);
Just4pLeisure 1:d5452e398b76 923 uint32_t file_size = ftell (fp);
Just4pLeisure 1:d5452e398b76 924 rewind (fp);
Just4pLeisure 1:d5452e398b76 925
Just4pLeisure 1:d5452e398b76 926 // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU
Just4pLeisure 1:d5452e398b76 927 uint8_t stack_byte = 0;
Just4pLeisure 1:d5452e398b76 928 uint32_t stack_long = 0;
Just4pLeisure 1:d5452e398b76 929 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 930 stack_long |= (stack_byte << 24);
Just4pLeisure 1:d5452e398b76 931 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 932 stack_long |= (stack_byte << 16);
Just4pLeisure 1:d5452e398b76 933 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 934 stack_long |= (stack_byte << 8);
Just4pLeisure 1:d5452e398b76 935 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 936 stack_long |= stack_byte;
Just4pLeisure 1:d5452e398b76 937 rewind (fp);
Just4pLeisure 1:d5452e398b76 938
Just4pLeisure 1:d5452e398b76 939 if (start == T52FLASHSTART && (file_size != T52FLASHSIZE || stack_long != T5POINTER)) {
Just4pLeisure 1:d5452e398b76 940 fclose(fp);
Just4pLeisure 1:d5452e398b76 941 printf("The BIN file does not appear to be for a T5.2 ECU :-(\r\n");
Just4pLeisure 1:d5452e398b76 942 printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, T52FLASHSIZE, stack_long);
Just4pLeisure 1:d5452e398b76 943 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 944 }
Just4pLeisure 1:d5452e398b76 945 if (start == T55FLASHSTART && (file_size != T55FLASHSIZE || stack_long != T5POINTER)) {
Just4pLeisure 1:d5452e398b76 946 fclose(fp);
Just4pLeisure 1:d5452e398b76 947 printf("The BIN file does not appear to be for a T5.5 ECU :-(\r\n");
Just4pLeisure 1:d5452e398b76 948 printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, T55FLASHSIZE, stack_long);
Just4pLeisure 1:d5452e398b76 949 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 950 }
Just4pLeisure 1:d5452e398b76 951
Just4pLeisure 1:d5452e398b76 952 char msg[8]; // Construct the bootloader frame for uploading
Just4pLeisure 1:d5452e398b76 953 uint32_t curr_addr = start; // address to put FLASH data
Just4pLeisure 1:d5452e398b76 954 uint8_t byte_value = 0;
Just4pLeisure 1:d5452e398b76 955
Just4pLeisure 5:1775b4b13232 956 printf(" 0.00 %% complete.\r");
Just4pLeisure 1:d5452e398b76 957 while (curr_addr <= TRIONICLASTADDR) {
Just4pLeisure 1:d5452e398b76 958
Just4pLeisure 1:d5452e398b76 959 // send a bootloader address message
Just4pLeisure 1:d5452e398b76 960 if (!t5_can_send_boot_address(curr_addr, 0x80)) {
Just4pLeisure 1:d5452e398b76 961 fclose(fp);
Just4pLeisure 5:1775b4b13232 962 printf("\r\nError sending Block Start message. Address: %08x\r\n",curr_addr);
Just4pLeisure 1:d5452e398b76 963 return FALSE;
Just4pLeisure 1:d5452e398b76 964 }
Just4pLeisure 1:d5452e398b76 965 // Construct and send the bootloader frames
Just4pLeisure 1:d5452e398b76 966 // 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 1:d5452e398b76 967 // 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 1:d5452e398b76 968 // in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame.
Just4pLeisure 1:d5452e398b76 969 for (uint8_t i=0; i<0x80; i++) {
Just4pLeisure 1:d5452e398b76 970 if (!fread(&byte_value,1,1,fp)) {
Just4pLeisure 1:d5452e398b76 971 fclose(fp);
Just4pLeisure 5:1775b4b13232 972 printf("\r\nError reading the BIN file MODIFIED.BIN\r\n");
Just4pLeisure 1:d5452e398b76 973 return FALSE;
Just4pLeisure 1:d5452e398b76 974 }
Just4pLeisure 1:d5452e398b76 975 msg[1+(i%7)] = byte_value;
Just4pLeisure 1:d5452e398b76 976 if (i%7 == 0) msg[0]=i; // set the index number
Just4pLeisure 1:d5452e398b76 977 if ((i%7 == 6) || (i == 0x80 - 1))
Just4pLeisure 1:d5452e398b76 978 if (!t5_can_send_boot_frame(msg)) {
Just4pLeisure 1:d5452e398b76 979 fclose(fp);
Just4pLeisure 5:1775b4b13232 980 printf("\r\nError sending a Block data message. Address: %08x, Index: %02x\r\n",curr_addr, i);
Just4pLeisure 1:d5452e398b76 981 return FALSE;
Just4pLeisure 1:d5452e398b76 982 }
Just4pLeisure 5:1775b4b13232 983
Just4pLeisure 1:d5452e398b76 984 }
Just4pLeisure 5:1775b4b13232 985 curr_addr += 0x80;
Just4pLeisure 5:1775b4b13232 986 printf("%6.2f\r", 100*(float)(curr_addr - start)/(float)(TRIONICLASTADDR - start) );
Just4pLeisure 1:d5452e398b76 987 }
Just4pLeisure 5:1775b4b13232 988 printf("100.00 %% complete.\r\n");
Just4pLeisure 1:d5452e398b76 989 fclose(fp);
Just4pLeisure 1:d5452e398b76 990 return TRUE;
Just4pLeisure 1:d5452e398b76 991 }
Just4pLeisure 1:d5452e398b76 992
Just4pLeisure 1:d5452e398b76 993 //
Just4pLeisure 1:d5452e398b76 994 // t5_can_send_flash_s19_update
Just4pLeisure 1:d5452e398b76 995 //
Just4pLeisure 1:d5452e398b76 996 // Sends a FLASH update file, modified.s19 to the T5 ECU.
Just4pLeisure 1:d5452e398b76 997 // The FLASH update file is stored on the local file system and must be in S19 format.
Just4pLeisure 1:d5452e398b76 998 //
Just4pLeisure 1:d5452e398b76 999 // FLASHing a T5.5 ECU takes around 60 seconds. FLASHing T5.2 ECUs should take about half of this time
Just4pLeisure 1:d5452e398b76 1000 //
Just4pLeisure 1:d5452e398b76 1001 // inputs: start start address of the T5.x FLASH
Just4pLeisure 1:d5452e398b76 1002
Just4pLeisure 1:d5452e398b76 1003 // return: bool TRUE if all went OK,
Just4pLeisure 1:d5452e398b76 1004 // FALSE if the FLASH update failed for some reason.
Just4pLeisure 1:d5452e398b76 1005 //
Just4pLeisure 5:1775b4b13232 1006 bool t5_can_send_flash_s19_update(uint32_t start)
Just4pLeisure 5:1775b4b13232 1007 {
Just4pLeisure 1:d5452e398b76 1008 printf("Programming the FLASH chips.\r\n");
Just4pLeisure 1:d5452e398b76 1009 FILE *fp = fopen("/local/modified.s19", "r"); // Open "modified.s19" on the local file system for reading
Just4pLeisure 1:d5452e398b76 1010 if (!fp) {
Just4pLeisure 1:d5452e398b76 1011 printf("Error: I could not find the BIN file MODIFIED.S19\r\n");
Just4pLeisure 1:d5452e398b76 1012 return FALSE;
Just4pLeisure 1:d5452e398b76 1013 }
Just4pLeisure 1:d5452e398b76 1014 int c = 0; // for some reason fgetc returns an int instead of a char
Just4pLeisure 1:d5452e398b76 1015 uint8_t count = 0; // count of bytes in the S-record can be 0xFF = 255 in decimal
Just4pLeisure 1:d5452e398b76 1016 uint8_t asize = 0; // 2,3 or 4 bytes in address
Just4pLeisure 1:d5452e398b76 1017 uint32_t address = 0; // address to put S-record
Just4pLeisure 1:d5452e398b76 1018 uint8_t checksum = 0; // checksum check at the end
Just4pLeisure 1:d5452e398b76 1019 char msg[8]; // Construct the bootloader frame for uploading
Just4pLeisure 1:d5452e398b76 1020 bool sent = FALSE;
Just4pLeisure 1:d5452e398b76 1021
Just4pLeisure 1:d5452e398b76 1022 while (!sent) {
Just4pLeisure 1:d5452e398b76 1023
Just4pLeisure 1:d5452e398b76 1024 do c = fgetc (fp); // get characters until we get an 'S' (throws away \n,\r characters and other junk)
Just4pLeisure 1:d5452e398b76 1025 while (c != 'S' && c != EOF);
Just4pLeisure 1:d5452e398b76 1026 // if (c == EOF) return '\a';
Just4pLeisure 1:d5452e398b76 1027 c = fgetc(fp); // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached)
Just4pLeisure 1:d5452e398b76 1028 // if ((c = fgetc(fp)) == EOF) return '\a'; // get the S-record type 1/2/3 5 7/8/9 (Return if EOF reached)
Just4pLeisure 1:d5452e398b76 1029 switch (c) {
Just4pLeisure 1:d5452e398b76 1030 case '0':
Just4pLeisure 1:d5452e398b76 1031 break; // Skip over S0 header record
Just4pLeisure 1:d5452e398b76 1032
Just4pLeisure 1:d5452e398b76 1033 case '1':
Just4pLeisure 1:d5452e398b76 1034 case '2':
Just4pLeisure 1:d5452e398b76 1035 case '3':
Just4pLeisure 1:d5452e398b76 1036 asize = 1 + c - '0'; // 2, 3 or 4 bytes for address
Just4pLeisure 1:d5452e398b76 1037 address = 0;
Just4pLeisure 1:d5452e398b76 1038 // get the number of bytes (in ascii format) in this S-record line
Just4pLeisure 1:d5452e398b76 1039 // there must be at least the address and the checksum so return with an error if less than this!
Just4pLeisure 1:d5452e398b76 1040 if ((c = SRecGetByte(fp)) < (asize + 1)) {
Just4pLeisure 1:d5452e398b76 1041 fclose(fp);
Just4pLeisure 1:d5452e398b76 1042 printf("Error in S-record address");
Just4pLeisure 1:d5452e398b76 1043 return FALSE;
Just4pLeisure 1:d5452e398b76 1044 }
Just4pLeisure 1:d5452e398b76 1045 count = c;
Just4pLeisure 1:d5452e398b76 1046 checksum = c;
Just4pLeisure 1:d5452e398b76 1047 // get the address
Just4pLeisure 1:d5452e398b76 1048 for (uint8_t i=0; i<asize; i++) {
Just4pLeisure 1:d5452e398b76 1049 c = SRecGetByte(fp);
Just4pLeisure 1:d5452e398b76 1050 checksum += c;
Just4pLeisure 1:d5452e398b76 1051 address <<= 8;
Just4pLeisure 1:d5452e398b76 1052 address |= c;
Just4pLeisure 1:d5452e398b76 1053 count--;
Just4pLeisure 1:d5452e398b76 1054 }
Just4pLeisure 1:d5452e398b76 1055 // send a bootloader address message - Adding the start address that was supplied (for T5.2/T5.5)
Just4pLeisure 1:d5452e398b76 1056 if (!t5_can_send_boot_address((address + start), (count - 1))) {
Just4pLeisure 1:d5452e398b76 1057 fclose(fp);
Just4pLeisure 1:d5452e398b76 1058 printf("Error sending CAN message");
Just4pLeisure 1:d5452e398b76 1059 return FALSE;
Just4pLeisure 1:d5452e398b76 1060 }
Just4pLeisure 1:d5452e398b76 1061 // get and send the bootloader frames for this S-record
Just4pLeisure 1:d5452e398b76 1062 // 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 1:d5452e398b76 1063 // 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 1:d5452e398b76 1064 // in the S-Record is sent with the upload address) and ignores any extra bytes in the last frame.
Just4pLeisure 1:d5452e398b76 1065 for (uint8_t i=0; i<count-1; i++) {
Just4pLeisure 1:d5452e398b76 1066 c = SRecGetByte(fp);
Just4pLeisure 1:d5452e398b76 1067 checksum += c;
Just4pLeisure 1:d5452e398b76 1068 msg[1+(i%7)] = c;
Just4pLeisure 1:d5452e398b76 1069 if (i%7 == 0) msg[0]=i; // set the index number
Just4pLeisure 1:d5452e398b76 1070 if ((i%7 == 6) || (i == count - 2))
Just4pLeisure 1:d5452e398b76 1071 if (!t5_can_send_boot_frame(msg)) {
Just4pLeisure 1:d5452e398b76 1072 fclose(fp);
Just4pLeisure 1:d5452e398b76 1073 printf("Error sending CAN message");
Just4pLeisure 1:d5452e398b76 1074 return FALSE;
Just4pLeisure 1:d5452e398b76 1075 }
Just4pLeisure 1:d5452e398b76 1076 }
Just4pLeisure 1:d5452e398b76 1077 // get the checksum
Just4pLeisure 1:d5452e398b76 1078 if ((checksum += SRecGetByte(fp)) != 0xFF) {
Just4pLeisure 1:d5452e398b76 1079 fclose(fp);
Just4pLeisure 1:d5452e398b76 1080 printf("Error in S-record, checksum = %2x\r\n", checksum);
Just4pLeisure 1:d5452e398b76 1081 return FALSE;
Just4pLeisure 1:d5452e398b76 1082 }
Just4pLeisure 1:d5452e398b76 1083 break;
Just4pLeisure 1:d5452e398b76 1084
Just4pLeisure 1:d5452e398b76 1085 case '5':
Just4pLeisure 1:d5452e398b76 1086 break; // Skip over S5 record types
Just4pLeisure 1:d5452e398b76 1087
Just4pLeisure 1:d5452e398b76 1088 case '7':
Just4pLeisure 1:d5452e398b76 1089 case '8':
Just4pLeisure 1:d5452e398b76 1090 case '9':
Just4pLeisure 1:d5452e398b76 1091 sent = TRUE;
Just4pLeisure 1:d5452e398b76 1092 break;
Just4pLeisure 1:d5452e398b76 1093
Just4pLeisure 1:d5452e398b76 1094 // Some kind of invalid S-record type so break
Just4pLeisure 1:d5452e398b76 1095 default:
Just4pLeisure 1:d5452e398b76 1096 printf("oops - didn't recognise that S-Record\r\n");
Just4pLeisure 1:d5452e398b76 1097 fclose(fp);
Just4pLeisure 1:d5452e398b76 1098 return FALSE;
Just4pLeisure 1:d5452e398b76 1099 }
Just4pLeisure 1:d5452e398b76 1100 }
Just4pLeisure 1:d5452e398b76 1101 fclose(fp);
Just4pLeisure 1:d5452e398b76 1102 return TRUE;
Just4pLeisure 1:d5452e398b76 1103 }
Just4pLeisure 1:d5452e398b76 1104
Just4pLeisure 1:d5452e398b76 1105 //
Just4pLeisure 1:d5452e398b76 1106 // t5_can_get_last_address
Just4pLeisure 1:d5452e398b76 1107 //
Just4pLeisure 1:d5452e398b76 1108 // Sends a C3 Message to the T5 ECU. The reply should contain the last used FLASH address
Just4pLeisure 1:d5452e398b76 1109 // which is always 0x0007FFFF
Just4pLeisure 1:d5452e398b76 1110 //
Just4pLeisure 1:d5452e398b76 1111 // The last 2 bytes of the message might be useful to work out whether or not the bootloader
Just4pLeisure 1:d5452e398b76 1112 // has been loaded. The 'mode' value will be 0x0808 when the bootloader is running or 0x89b8
Just4pLeisure 1:d5452e398b76 1113 // when it isn't.
Just4pLeisure 1:d5452e398b76 1114 //
Just4pLeisure 1:d5452e398b76 1115 // inputs: none
Just4pLeisure 1:d5452e398b76 1116 // return: bool TRUE if all went OK,
Just4pLeisure 1:d5452e398b76 1117 //
Just4pLeisure 5:1775b4b13232 1118 bool t5_can_get_last_address()
Just4pLeisure 5:1775b4b13232 1119 {
Just4pLeisure 1:d5452e398b76 1120 uint32_t last_address = 0;
Just4pLeisure 1:d5452e398b76 1121 uint16_t mode = 0;
Just4pLeisure 1:d5452e398b76 1122 if (!t5_boot_c3_command(&last_address, &mode)) {
Just4pLeisure 1:d5452e398b76 1123 printf("Error trying to find out the ECU's last address and mode!\r\n");
Just4pLeisure 1:d5452e398b76 1124 return FALSE;
Just4pLeisure 1:d5452e398b76 1125 }
Just4pLeisure 1:d5452e398b76 1126 printf("The Last used FLASH address is: %#010x, mode %#06x\r\n", last_address, mode);
Just4pLeisure 1:d5452e398b76 1127 return TRUE;
Just4pLeisure 1:d5452e398b76 1128 }