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