Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
t8utils.cpp@6:2fbcbebed28c, 2016-04-23 (annotated)
- 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?
User | Revision | Line number | New contents of line |
---|---|---|---|
Just4pLeisure | 4:682d96ff6d79 | 1 | /******************************************************************************* |
Just4pLeisure | 4:682d96ff6d79 | 2 | |
Just4pLeisure | 4:682d96ff6d79 | 3 | t7utils.cpp |
Just4pLeisure | 4:682d96ff6d79 | 4 | (c) 2011, 2012 by Sophie Dexter |
Just4pLeisure | 4:682d96ff6d79 | 5 | portions (c) Tomi Liljemark (firstname.surname@gmail.com) |
Just4pLeisure | 4:682d96ff6d79 | 6 | |
Just4pLeisure | 4:682d96ff6d79 | 7 | This C++ module provides functions for communicating simple messages to and from |
Just4pLeisure | 4:682d96ff6d79 | 8 | the T7 ECU |
Just4pLeisure | 4:682d96ff6d79 | 9 | |
Just4pLeisure | 4:682d96ff6d79 | 10 | ******************************************************************************** |
Just4pLeisure | 4:682d96ff6d79 | 11 | |
Just4pLeisure | 4:682d96ff6d79 | 12 | WARNING: Use at your own risk, sadly this software comes with no guarantees. |
Just4pLeisure | 4:682d96ff6d79 | 13 | This software is provided 'free' and in good faith, but the author does not |
Just4pLeisure | 4:682d96ff6d79 | 14 | accept liability for any damage arising from its use. |
Just4pLeisure | 4:682d96ff6d79 | 15 | |
Just4pLeisure | 4:682d96ff6d79 | 16 | *******************************************************************************/ |
Just4pLeisure | 4:682d96ff6d79 | 17 | |
Just4pLeisure | 4:682d96ff6d79 | 18 | #include "t8utils.h" |
Just4pLeisure | 4:682d96ff6d79 | 19 | |
Just4pLeisure | 4:682d96ff6d79 | 20 | Timer TesterPresent; |
Just4pLeisure | 4:682d96ff6d79 | 21 | |
Just4pLeisure | 4:682d96ff6d79 | 22 | |
Just4pLeisure | 4:682d96ff6d79 | 23 | // |
Just4pLeisure | 4:682d96ff6d79 | 24 | // t8_initialise |
Just4pLeisure | 4:682d96ff6d79 | 25 | // |
Just4pLeisure | 4:682d96ff6d79 | 26 | // sends an initialisation message to the T7 ECU |
Just4pLeisure | 4:682d96ff6d79 | 27 | // but doesn't displays anything. |
Just4pLeisure | 4:682d96ff6d79 | 28 | // |
Just4pLeisure | 4:682d96ff6d79 | 29 | // inputs: none |
Just4pLeisure | 4:682d96ff6d79 | 30 | // return: bool TRUE if there was a message, FALSE if no message. |
Just4pLeisure | 4:682d96ff6d79 | 31 | // |
Just4pLeisure | 4:682d96ff6d79 | 32 | |
Just4pLeisure | 4:682d96ff6d79 | 33 | |
Just4pLeisure | 4:682d96ff6d79 | 34 | bool t8_initialise() |
Just4pLeisure | 4:682d96ff6d79 | 35 | { |
Just4pLeisure | 4:682d96ff6d79 | 36 | return TRUE; |
Just4pLeisure | 4:682d96ff6d79 | 37 | } |
Just4pLeisure | 4:682d96ff6d79 | 38 | |
Just4pLeisure | 4:682d96ff6d79 | 39 | bool t8_show_VIN() |
Just4pLeisure | 4:682d96ff6d79 | 40 | { |
Just4pLeisure | 5:1775b4b13232 | 41 | uint32_t i; |
Just4pLeisure | 4:682d96ff6d79 | 42 | char T8TxFlo[] = T8FLOCTL; |
Just4pLeisure | 4:682d96ff6d79 | 43 | char T8TxMsg[] = T8REQVIN; |
Just4pLeisure | 4:682d96ff6d79 | 44 | char T8RxMsg[8]; |
Just4pLeisure | 4:682d96ff6d79 | 45 | printf("Requesting VIN from T8...\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 46 | // Send "Request VIN" to Trionic8 |
Just4pLeisure | 4:682d96ff6d79 | 47 | if (!can_send_timeout (T8TSTRID, T8TxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 48 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 49 | // wait for the T8 to reply |
Just4pLeisure | 4:682d96ff6d79 | 50 | // Read "Seed" |
Just4pLeisure | 4:682d96ff6d79 | 51 | // if a message is not received id return false |
Just4pLeisure | 4:682d96ff6d79 | 52 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 53 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 54 | //* DEBUG info... |
Just4pLeisure | 4:682d96ff6d79 | 55 | for (i = 0; i < 8; i++ ) printf("0x%02X ", T8RxMsg[i] ); |
Just4pLeisure | 4:682d96ff6d79 | 56 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 57 | for (i = 5; i < 8; i++ ) printf("%c", T8RxMsg[i] ); |
Just4pLeisure | 4:682d96ff6d79 | 58 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 59 | // Send Trionic8 a "Flow Control Message to get the rest of the VIN |
Just4pLeisure | 4:682d96ff6d79 | 60 | if (!can_send_timeout (T8TSTRID, T8TxFlo, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 61 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 62 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 63 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 64 | //* DEBUG info... |
Just4pLeisure | 4:682d96ff6d79 | 65 | for (i = 0; i < 8; i++ ) printf("0x%02X ", T8RxMsg[i] ); |
Just4pLeisure | 4:682d96ff6d79 | 66 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 67 | for (i = 1; i < 8; i++ ) printf("%c", T8RxMsg[i] ); |
Just4pLeisure | 4:682d96ff6d79 | 68 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 69 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 70 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 71 | //* DEBUG info... |
Just4pLeisure | 4:682d96ff6d79 | 72 | for (i = 0; i < 8; i++ ) printf("0x%02X ", T8RxMsg[i] ); |
Just4pLeisure | 4:682d96ff6d79 | 73 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 74 | for (i = 1; i < 8; i++ ) printf("%c", T8RxMsg[i] ); |
Just4pLeisure | 4:682d96ff6d79 | 75 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 76 | //*/ |
Just4pLeisure | 4:682d96ff6d79 | 77 | return TRUE; |
Just4pLeisure | 4:682d96ff6d79 | 78 | } |
Just4pLeisure | 4:682d96ff6d79 | 79 | |
Just4pLeisure | 4:682d96ff6d79 | 80 | bool t8_write_VIN() |
Just4pLeisure | 4:682d96ff6d79 | 81 | { |
Just4pLeisure | 4:682d96ff6d79 | 82 | |
Just4pLeisure | 4:682d96ff6d79 | 83 | char SetVin10[] = {0x10,0x13,0x3B,0x90,0x59,0x53,0x33,0x46}; |
Just4pLeisure | 4:682d96ff6d79 | 84 | char SetVin21[] = {0x21,0x46,0x34,0x35,0x53,0x38,0x33,0x31}; |
Just4pLeisure | 4:682d96ff6d79 | 85 | // char SetVin22[] = {0x22,0x30,0x30,0x32,0x33,0x34,0x30,0xaa}; // Original |
Just4pLeisure | 4:682d96ff6d79 | 86 | char SetVin22[] = {0x22,0x30,0x30,0x34,0x33,0x32,0x31,0x00}; |
Just4pLeisure | 4:682d96ff6d79 | 87 | char T8RxMsg[8]; |
Just4pLeisure | 4:682d96ff6d79 | 88 | char k = 0; |
Just4pLeisure | 4:682d96ff6d79 | 89 | |
Just4pLeisure | 5:1775b4b13232 | 90 | // GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 91 | // wait_ms(2000); |
Just4pLeisure | 4:682d96ff6d79 | 92 | // |
Just4pLeisure | 4:682d96ff6d79 | 93 | // printf("Requesting Security Access\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 94 | // if (!t8_authenticate(0x01)) { |
Just4pLeisure | 4:682d96ff6d79 | 95 | // printf("Unable to get Security Access\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 96 | // return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 97 | // } |
Just4pLeisure | 4:682d96ff6d79 | 98 | // printf("Security Access Granted\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 99 | // |
Just4pLeisure | 5:1775b4b13232 | 100 | // GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 101 | // wait_ms(2000); |
Just4pLeisure | 4:682d96ff6d79 | 102 | // |
Just4pLeisure | 5:1775b4b13232 | 103 | // GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 104 | // wait_ms(2000); |
Just4pLeisure | 4:682d96ff6d79 | 105 | // |
Just4pLeisure | 4:682d96ff6d79 | 106 | if (!can_send_timeout (T8TSTRID, SetVin10, 8, T8MESSAGETIMEOUT)) { |
Just4pLeisure | 4:682d96ff6d79 | 107 | printf("Unable to write VIN\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 108 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 109 | } |
Just4pLeisure | 4:682d96ff6d79 | 110 | for (k = 0; k < 8; k++ ) printf("0x%02X ", SetVin10[k] ); |
Just4pLeisure | 4:682d96ff6d79 | 111 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 112 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 113 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 114 | for (k = 0; k < 8; k++ ) printf("0x%02X ", T8RxMsg[k] ); |
Just4pLeisure | 4:682d96ff6d79 | 115 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 116 | // wait_ms(100); |
Just4pLeisure | 4:682d96ff6d79 | 117 | if (!can_send_timeout (T8TSTRID, SetVin21, 8, T8MESSAGETIMEOUT)) { |
Just4pLeisure | 4:682d96ff6d79 | 118 | printf("Unable to write VIN\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 119 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 120 | } |
Just4pLeisure | 4:682d96ff6d79 | 121 | for (k = 0; k < 8; k++ ) printf("0x%02X ", SetVin21[k] ); |
Just4pLeisure | 4:682d96ff6d79 | 122 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 123 | // wait_ms(100); |
Just4pLeisure | 4:682d96ff6d79 | 124 | if (!can_send_timeout (T8TSTRID, SetVin22, 8, T8MESSAGETIMEOUT)) { |
Just4pLeisure | 4:682d96ff6d79 | 125 | printf("Unable to write VIN\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 126 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 127 | } |
Just4pLeisure | 4:682d96ff6d79 | 128 | for (k = 0; k < 8; k++ ) printf("0x%02X ", SetVin22[k] ); |
Just4pLeisure | 4:682d96ff6d79 | 129 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 130 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 131 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 132 | for (k = 0; k < 8; k++ ) printf("0x%02X ", T8RxMsg[k] ); |
Just4pLeisure | 4:682d96ff6d79 | 133 | printf("\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 134 | return TRUE; |
Just4pLeisure | 5:1775b4b13232 | 135 | // GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 136 | // wait_ms(2000); |
Just4pLeisure | 4:682d96ff6d79 | 137 | // |
Just4pLeisure | 4:682d96ff6d79 | 138 | } |
Just4pLeisure | 4:682d96ff6d79 | 139 | |
Just4pLeisure | 4:682d96ff6d79 | 140 | // |
Just4pLeisure | 4:682d96ff6d79 | 141 | // t8_authenticate |
Just4pLeisure | 4:682d96ff6d79 | 142 | // |
Just4pLeisure | 4:682d96ff6d79 | 143 | // sends an authentication message to the T7 ECU |
Just4pLeisure | 4:682d96ff6d79 | 144 | // but doesn't display anything. |
Just4pLeisure | 4:682d96ff6d79 | 145 | // |
Just4pLeisure | 4:682d96ff6d79 | 146 | // inputs: none |
Just4pLeisure | 4:682d96ff6d79 | 147 | // return: bool TRUE if there was a message, FALSE if no message. |
Just4pLeisure | 4:682d96ff6d79 | 148 | // |
Just4pLeisure | 4:682d96ff6d79 | 149 | |
Just4pLeisure | 5:1775b4b13232 | 150 | bool t8_authenticate(uint32_t ReqID, uint32_t RespID, char level) |
Just4pLeisure | 4:682d96ff6d79 | 151 | { |
Just4pLeisure | 5:1775b4b13232 | 152 | uint16_t i, seed, key; |
Just4pLeisure | 5:1775b4b13232 | 153 | // if (!GMLANSecurityAccessRequest(ReqID, RespID, level, seed)) { |
Just4pLeisure | 5:1775b4b13232 | 154 | // printf("Unable to request SEED value for security access\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 155 | // return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 156 | // } |
Just4pLeisure | 5:1775b4b13232 | 157 | |
Just4pLeisure | 5:1775b4b13232 | 158 | for (i=0; i < 20; i++) { |
Just4pLeisure | 5:1775b4b13232 | 159 | if (GMLANSecurityAccessRequest(ReqID, RespID, level, seed)) |
Just4pLeisure | 5:1775b4b13232 | 160 | break; |
Just4pLeisure | 5:1775b4b13232 | 161 | wait(1); |
Just4pLeisure | 5:1775b4b13232 | 162 | GMLANTesterPresent(ReqID, RespID); |
Just4pLeisure | 5:1775b4b13232 | 163 | } |
Just4pLeisure | 5:1775b4b13232 | 164 | if (i == 20) { |
Just4pLeisure | 4:682d96ff6d79 | 165 | printf("Unable to request SEED value for security access\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 166 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 167 | } |
Just4pLeisure | 5:1775b4b13232 | 168 | |
Just4pLeisure | 4:682d96ff6d79 | 169 | if ( seed == 0x0000 ) { |
Just4pLeisure | 4:682d96ff6d79 | 170 | printf("T8 ECU is already unlocked\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 171 | return TRUE; |
Just4pLeisure | 4:682d96ff6d79 | 172 | } |
Just4pLeisure | 4:682d96ff6d79 | 173 | key = (seed >> 5) | (seed << 11); |
Just4pLeisure | 4:682d96ff6d79 | 174 | key += 0xB988; |
Just4pLeisure | 4:682d96ff6d79 | 175 | if (level == 0xFD) { |
Just4pLeisure | 4:682d96ff6d79 | 176 | key /= 3; |
Just4pLeisure | 4:682d96ff6d79 | 177 | key ^= 0x8749; |
Just4pLeisure | 4:682d96ff6d79 | 178 | key += 0x0ACF; |
Just4pLeisure | 4:682d96ff6d79 | 179 | key ^= 0x81BF; |
Just4pLeisure | 4:682d96ff6d79 | 180 | } else if (level == 0xFB) { |
Just4pLeisure | 4:682d96ff6d79 | 181 | key ^= 0x8749; |
Just4pLeisure | 4:682d96ff6d79 | 182 | key += 0x06D3; |
Just4pLeisure | 4:682d96ff6d79 | 183 | key ^= 0xCFDF; |
Just4pLeisure | 4:682d96ff6d79 | 184 | } |
Just4pLeisure | 4:682d96ff6d79 | 185 | /* CIM KEY CALCULATION |
Just4pLeisure | 4:682d96ff6d79 | 186 | uint16_t key = (seed + 0x9130); |
Just4pLeisure | 4:682d96ff6d79 | 187 | key = (key >> 8) | (key << 8); |
Just4pLeisure | 4:682d96ff6d79 | 188 | key -= 0x3FC7; |
Just4pLeisure | 4:682d96ff6d79 | 189 | */ |
Just4pLeisure | 5:1775b4b13232 | 190 | wait_ms(1); |
Just4pLeisure | 5:1775b4b13232 | 191 | if (!GMLANSecurityAccessSendKey(ReqID, RespID, level, key)) { |
Just4pLeisure | 4:682d96ff6d79 | 192 | printf("Unable to send KEY value for security access\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 193 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 194 | } |
Just4pLeisure | 4:682d96ff6d79 | 195 | printf("Key Accepted\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 196 | wait_ms(500); // was 5 |
Just4pLeisure | 4:682d96ff6d79 | 197 | return TRUE; |
Just4pLeisure | 4:682d96ff6d79 | 198 | } |
Just4pLeisure | 4:682d96ff6d79 | 199 | |
Just4pLeisure | 4:682d96ff6d79 | 200 | |
Just4pLeisure | 4:682d96ff6d79 | 201 | // |
Just4pLeisure | 4:682d96ff6d79 | 202 | // t8_dump |
Just4pLeisure | 4:682d96ff6d79 | 203 | // |
Just4pLeisure | 4:682d96ff6d79 | 204 | // dumps the T8 BIN File |
Just4pLeisure | 4:682d96ff6d79 | 205 | // but doesn't displays anything. |
Just4pLeisure | 4:682d96ff6d79 | 206 | // |
Just4pLeisure | 4:682d96ff6d79 | 207 | // inputs: none |
Just4pLeisure | 4:682d96ff6d79 | 208 | // return: bool TRUE if there was a message, FALSE if no message. |
Just4pLeisure | 4:682d96ff6d79 | 209 | // |
Just4pLeisure | 4:682d96ff6d79 | 210 | |
Just4pLeisure | 4:682d96ff6d79 | 211 | bool t8_dump() |
Just4pLeisure | 4:682d96ff6d79 | 212 | { |
Just4pLeisure | 5:1775b4b13232 | 213 | uint32_t i = 0, k = 0; |
Just4pLeisure | 4:682d96ff6d79 | 214 | char T8TxMsg[8]; |
Just4pLeisure | 4:682d96ff6d79 | 215 | char T8RxMsg[8]; |
Just4pLeisure | 4:682d96ff6d79 | 216 | |
Just4pLeisure | 4:682d96ff6d79 | 217 | timer.reset(); |
Just4pLeisure | 4:682d96ff6d79 | 218 | timer.start(); |
Just4pLeisure | 4:682d96ff6d79 | 219 | printf("Creating FLASH dump file...\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 220 | |
Just4pLeisure | 4:682d96ff6d79 | 221 | // |
Just4pLeisure | 5:1775b4b13232 | 222 | if (!GMLANprogrammingSetupProcess(T8REQID, T8RESPID)) |
Just4pLeisure | 4:682d96ff6d79 | 223 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 224 | // |
Just4pLeisure | 4:682d96ff6d79 | 225 | printf("Requesting Security Access\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 226 | if (!t8_authenticate(T8REQID, T8RESPID, 0x01)) { |
Just4pLeisure | 4:682d96ff6d79 | 227 | printf("Unable to get Security Access\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 228 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 229 | } |
Just4pLeisure | 4:682d96ff6d79 | 230 | printf("Security Access Granted\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 231 | // |
Just4pLeisure | 5:1775b4b13232 | 232 | if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, T8BootloaderRead)) |
Just4pLeisure | 4:682d96ff6d79 | 233 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 234 | // |
Just4pLeisure | 4:682d96ff6d79 | 235 | // |
Just4pLeisure | 4:682d96ff6d79 | 236 | printf("Downloading FLASH BIN file...\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 237 | printf("Creating FLASH dump file...\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 238 | FILE *fp = fopen("/local/original.bin", "w"); // Open "original.bin" on the local file system for writing |
Just4pLeisure | 4:682d96ff6d79 | 239 | if (!fp) { |
Just4pLeisure | 4:682d96ff6d79 | 240 | perror ("The following error occured"); |
Just4pLeisure | 4:682d96ff6d79 | 241 | return TERM_ERR; |
Just4pLeisure | 4:682d96ff6d79 | 242 | } |
Just4pLeisure | 4:682d96ff6d79 | 243 | printf(" 0.00 %% complete.\r"); |
Just4pLeisure | 4:682d96ff6d79 | 244 | TesterPresent.start(); |
Just4pLeisure | 5:1775b4b13232 | 245 | |
Just4pLeisure | 5:1775b4b13232 | 246 | // It is possible to save some time by only reading the program code and CAL data |
Just4pLeisure | 5:1775b4b13232 | 247 | // This is just a rough calculation, and slight overestimate of the number of blocks of data needed to send the BIN file |
Just4pLeisure | 5:1775b4b13232 | 248 | T8TxMsg[0] = 0x06; |
Just4pLeisure | 5:1775b4b13232 | 249 | T8TxMsg[1] = 0x21; |
Just4pLeisure | 5:1775b4b13232 | 250 | T8TxMsg[2] = 0x80; // Blocksize |
Just4pLeisure | 5:1775b4b13232 | 251 | T8TxMsg[3] = 0x00; // This address (0x020140) points to the Header at the end of the BIN |
Just4pLeisure | 5:1775b4b13232 | 252 | T8TxMsg[4] = 0x02; |
Just4pLeisure | 5:1775b4b13232 | 253 | T8TxMsg[5] = 0x01; |
Just4pLeisure | 5:1775b4b13232 | 254 | T8TxMsg[6] = 0x40; |
Just4pLeisure | 5:1775b4b13232 | 255 | T8TxMsg[7] = 0xaa; |
Just4pLeisure | 5:1775b4b13232 | 256 | if (!can_send_timeout (T8TSTRID, T8TxMsg, 7, T8MESSAGETIMEOUT)) { |
Just4pLeisure | 5:1775b4b13232 | 257 | printf("Unable to download FLASH\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 258 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 259 | } |
Just4pLeisure | 5:1775b4b13232 | 260 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 5:1775b4b13232 | 261 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 262 | uint32_t EndAddress = (T8RxMsg[5] << 16) | (T8RxMsg[6] << 8) | T8RxMsg[7]; |
Just4pLeisure | 5:1775b4b13232 | 263 | EndAddress += 0x200; // Add some bytes for the Footer itself and to account for division rounded down later |
Just4pLeisure | 5:1775b4b13232 | 264 | char T8TxFlo[] = T8FLOCTL; |
Just4pLeisure | 5:1775b4b13232 | 265 | can_send_timeout (T8TSTRID, T8TxFlo, 8, T8MESSAGETIMEOUT); |
Just4pLeisure | 5:1775b4b13232 | 266 | for (i = 0; i < 0x12; i++) { |
Just4pLeisure | 5:1775b4b13232 | 267 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 5:1775b4b13232 | 268 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 269 | } |
Just4pLeisure | 5:1775b4b13232 | 270 | printf("Reading your BIN file adjusted for footer = 0x%06X Bytes\r\n", EndAddress ); |
Just4pLeisure | 5:1775b4b13232 | 271 | |
Just4pLeisure | 5:1775b4b13232 | 272 | for ( uint32_t StartAddress = 0x0; StartAddress < EndAddress; StartAddress +=0x80 ) { // 0x100000 |
Just4pLeisure | 4:682d96ff6d79 | 273 | T8TxMsg[0] = 0x06; |
Just4pLeisure | 4:682d96ff6d79 | 274 | T8TxMsg[1] = 0x21; |
Just4pLeisure | 4:682d96ff6d79 | 275 | T8TxMsg[2] = 0x80; // Blocksize |
Just4pLeisure | 4:682d96ff6d79 | 276 | T8TxMsg[3] = (char) (StartAddress >> 24); |
Just4pLeisure | 4:682d96ff6d79 | 277 | T8TxMsg[4] = (char) (StartAddress >> 16); |
Just4pLeisure | 4:682d96ff6d79 | 278 | T8TxMsg[5] = (char) (StartAddress >> 8); |
Just4pLeisure | 4:682d96ff6d79 | 279 | T8TxMsg[6] = (char) (StartAddress); |
Just4pLeisure | 4:682d96ff6d79 | 280 | T8TxMsg[7] = 0xaa; |
Just4pLeisure | 4:682d96ff6d79 | 281 | #ifdef DEBUG |
Just4pLeisure | 4:682d96ff6d79 | 282 | printf("block %#.3f\r\n",timer.read()); |
Just4pLeisure | 4:682d96ff6d79 | 283 | #endif |
Just4pLeisure | 4:682d96ff6d79 | 284 | if (!can_send_timeout (T8TSTRID, T8TxMsg, 7, T8MESSAGETIMEOUT)) { |
Just4pLeisure | 4:682d96ff6d79 | 285 | printf("Unable to download FLASH\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 286 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 287 | } |
Just4pLeisure | 4:682d96ff6d79 | 288 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 289 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 290 | #ifdef DEBUG |
Just4pLeisure | 4:682d96ff6d79 | 291 | printf("first %#.3f\r\n",timer.read()); |
Just4pLeisure | 4:682d96ff6d79 | 292 | #endif |
Just4pLeisure | 5:1775b4b13232 | 293 | uint32_t txpnt = 0; |
Just4pLeisure | 4:682d96ff6d79 | 294 | for (k = 4; k < 8; k++ ) file_buffer[txpnt++] = T8RxMsg[k]; |
Just4pLeisure | 4:682d96ff6d79 | 295 | |
Just4pLeisure | 4:682d96ff6d79 | 296 | uint8_t DataFrames = 0x12; |
Just4pLeisure | 5:1775b4b13232 | 297 | char iFrameNumber = 0x21; |
Just4pLeisure | 4:682d96ff6d79 | 298 | char T8TxFlo[] = T8FLOCTL; |
Just4pLeisure | 5:1775b4b13232 | 299 | can_send_timeout (T8TSTRID, T8TxFlo, 8, T8MESSAGETIMEOUT); |
Just4pLeisure | 4:682d96ff6d79 | 300 | #ifdef DEBUG |
Just4pLeisure | 4:682d96ff6d79 | 301 | printf("flowCtrl %#.3f\r\n",timer.read()); |
Just4pLeisure | 4:682d96ff6d79 | 302 | #endif |
Just4pLeisure | 4:682d96ff6d79 | 303 | for (i = 0; i < DataFrames; i++) { |
Just4pLeisure | 4:682d96ff6d79 | 304 | if (!can_wait_timeout(T8ECU_ID, T8RxMsg, 8, T8MESSAGETIMEOUT)) |
Just4pLeisure | 4:682d96ff6d79 | 305 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 306 | #ifdef DEBUG |
Just4pLeisure | 4:682d96ff6d79 | 307 | printf("Consec %#.3f\r\n",timer.read()); |
Just4pLeisure | 4:682d96ff6d79 | 308 | #endif |
Just4pLeisure | 4:682d96ff6d79 | 309 | iFrameNumber++; |
Just4pLeisure | 4:682d96ff6d79 | 310 | for (k = 1; k < 8; k++ ) file_buffer[txpnt++] = T8RxMsg[k]; |
Just4pLeisure | 4:682d96ff6d79 | 311 | } |
Just4pLeisure | 4:682d96ff6d79 | 312 | fwrite((file_buffer), 1, 0x80, fp); |
Just4pLeisure | 4:682d96ff6d79 | 313 | if (ferror (fp)) { |
Just4pLeisure | 4:682d96ff6d79 | 314 | fclose (fp); |
Just4pLeisure | 4:682d96ff6d79 | 315 | printf ("Error writing to the FLASH BIN file.\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 316 | return TERM_ERR; |
Just4pLeisure | 4:682d96ff6d79 | 317 | } |
Just4pLeisure | 5:1775b4b13232 | 318 | printf("%6.2f\r", (100.0*(float)StartAddress)/(float)(EndAddress) ); |
Just4pLeisure | 4:682d96ff6d79 | 319 | if (TesterPresent.read_ms() > 2000) { |
Just4pLeisure | 5:1775b4b13232 | 320 | GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 321 | TesterPresent.reset(); |
Just4pLeisure | 5:1775b4b13232 | 322 | } |
Just4pLeisure | 5:1775b4b13232 | 323 | } |
Just4pLeisure | 5:1775b4b13232 | 324 | |
Just4pLeisure | 5:1775b4b13232 | 325 | for (uint32_t i = 0; i < 0x80; i++) |
Just4pLeisure | 5:1775b4b13232 | 326 | file_buffer[i] = 0xFF; |
Just4pLeisure | 5:1775b4b13232 | 327 | while ( ftell(fp) < 0x100000 ) { |
Just4pLeisure | 5:1775b4b13232 | 328 | // for ( uint32_t StartAddress = EndAddress; StartAddress < 0x100000; StartAddress +=0x80 ) { |
Just4pLeisure | 5:1775b4b13232 | 329 | fwrite((file_buffer), 1, 0x80, fp); |
Just4pLeisure | 5:1775b4b13232 | 330 | if (ferror (fp)) { |
Just4pLeisure | 5:1775b4b13232 | 331 | fclose (fp); |
Just4pLeisure | 5:1775b4b13232 | 332 | printf ("Error writing to the FLASH BIN file.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 333 | return TERM_ERR; |
Just4pLeisure | 4:682d96ff6d79 | 334 | } |
Just4pLeisure | 4:682d96ff6d79 | 335 | } |
Just4pLeisure | 4:682d96ff6d79 | 336 | |
Just4pLeisure | 4:682d96ff6d79 | 337 | printf("%6.2f\r\n", (float)100 ); |
Just4pLeisure | 4:682d96ff6d79 | 338 | timer.stop(); |
Just4pLeisure | 4:682d96ff6d79 | 339 | printf("SUCCESS! Getting the FLASH dump took %#.1f seconds.\r\n",timer.read()); |
Just4pLeisure | 4:682d96ff6d79 | 340 | fclose(fp); |
Just4pLeisure | 4:682d96ff6d79 | 341 | return TRUE; |
Just4pLeisure | 4:682d96ff6d79 | 342 | } |
Just4pLeisure | 4:682d96ff6d79 | 343 | |
Just4pLeisure | 4:682d96ff6d79 | 344 | |
Just4pLeisure | 4:682d96ff6d79 | 345 | bool t8_flash() |
Just4pLeisure | 4:682d96ff6d79 | 346 | { |
Just4pLeisure | 5:1775b4b13232 | 347 | uint32_t i = 0, j = 0, k = 0; |
Just4pLeisure | 4:682d96ff6d79 | 348 | |
Just4pLeisure | 4:682d96ff6d79 | 349 | timer.reset(); |
Just4pLeisure | 4:682d96ff6d79 | 350 | timer.start(); |
Just4pLeisure | 4:682d96ff6d79 | 351 | printf("FLASHing T8 BIN file...\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 352 | |
Just4pLeisure | 4:682d96ff6d79 | 353 | // |
Just4pLeisure | 5:1775b4b13232 | 354 | if (!GMLANprogrammingSetupProcess(T8REQID, T8RESPID)) |
Just4pLeisure | 4:682d96ff6d79 | 355 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 356 | // |
Just4pLeisure | 4:682d96ff6d79 | 357 | printf("Requesting Security Access\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 358 | if (!t8_authenticate(T8REQID, T8RESPID, 0x01)) { |
Just4pLeisure | 4:682d96ff6d79 | 359 | printf("Unable to get Security Access\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 360 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 361 | } |
Just4pLeisure | 4:682d96ff6d79 | 362 | printf("Security Access Granted\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 363 | // |
Just4pLeisure | 6:2fbcbebed28c | 364 | // All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) |
Just4pLeisure | 5:1775b4b13232 | 365 | // const uint8_t BootLoader[] = T8BootloaderProg; |
Just4pLeisure | 5:1775b4b13232 | 366 | // if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, BootLoader)) |
Just4pLeisure | 5:1775b4b13232 | 367 | if(!GMLANprogrammingUtilityFileProcess(T8REQID, T8RESPID, T8BootLoaderWrite)) |
Just4pLeisure | 4:682d96ff6d79 | 368 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 369 | // |
Just4pLeisure | 4:682d96ff6d79 | 370 | uint32_t StartAddress = 0x020000; |
Just4pLeisure | 5:1775b4b13232 | 371 | uint32_t txpnt = 0; |
Just4pLeisure | 4:682d96ff6d79 | 372 | char iFrameNumber = 0x21; |
Just4pLeisure | 4:682d96ff6d79 | 373 | char GMLANMsg[8]; |
Just4pLeisure | 4:682d96ff6d79 | 374 | char data2Send[0xE0]; |
Just4pLeisure | 4:682d96ff6d79 | 375 | // |
Just4pLeisure | 5:1775b4b13232 | 376 | // fopen modified.bin here, check it is OK and work out how much data I need to send |
Just4pLeisure | 4:682d96ff6d79 | 377 | // need lots of fcloses though |
Just4pLeisure | 4:682d96ff6d79 | 378 | printf("Checking the FLASH BIN file...\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 379 | FILE *fp = fopen("/local/modified.bin", "r"); // Open "modified.bin" on the local file system for reading |
Just4pLeisure | 4:682d96ff6d79 | 380 | if (!fp) { |
Just4pLeisure | 5:1775b4b13232 | 381 | printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");; |
Just4pLeisure | 4:682d96ff6d79 | 382 | return TERM_ERR; |
Just4pLeisure | 4:682d96ff6d79 | 383 | } |
Just4pLeisure | 4:682d96ff6d79 | 384 | // obtain file size - it should match the size of the FLASH chips: |
Just4pLeisure | 4:682d96ff6d79 | 385 | fseek (fp , 0 , SEEK_END); |
Just4pLeisure | 4:682d96ff6d79 | 386 | uint32_t file_size = ftell (fp); |
Just4pLeisure | 4:682d96ff6d79 | 387 | rewind (fp); |
Just4pLeisure | 4:682d96ff6d79 | 388 | |
Just4pLeisure | 4:682d96ff6d79 | 389 | // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU |
Just4pLeisure | 4:682d96ff6d79 | 390 | uint32_t stack_long = 0; |
Just4pLeisure | 5:1775b4b13232 | 391 | if (!fread(&stack_long,4,1,fp)) { |
Just4pLeisure | 5:1775b4b13232 | 392 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 393 | return TERM_ERR; |
Just4pLeisure | 5:1775b4b13232 | 394 | } |
Just4pLeisure | 4:682d96ff6d79 | 395 | stack_long = (stack_long >> 24) | ((stack_long << 8) & 0x00FF0000) | ((stack_long >> 8) & 0x0000FF00) | (stack_long << 24); |
Just4pLeisure | 4:682d96ff6d79 | 396 | // |
Just4pLeisure | 4:682d96ff6d79 | 397 | if (file_size != T8FLASHSIZE || stack_long != T8POINTER) { |
Just4pLeisure | 4:682d96ff6d79 | 398 | fclose(fp); |
Just4pLeisure | 4:682d96ff6d79 | 399 | printf("The BIN file does not appear to be for a T8 ECU :-(\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 400 | printf("BIN file size: %#010x, FLASH chip size: %#010x, Pointer: %#010x.\r\n", file_size, T7FLASHSIZE, stack_long); |
Just4pLeisure | 4:682d96ff6d79 | 401 | return TERM_ERR; |
Just4pLeisure | 4:682d96ff6d79 | 402 | } |
Just4pLeisure | 4:682d96ff6d79 | 403 | // It is possible to save some time by only sending the program code and CAL data |
Just4pLeisure | 4:682d96ff6d79 | 404 | // This is just a rough calculation, and slight overestimate of the number of blocks of data needed to send the BIN file |
Just4pLeisure | 4:682d96ff6d79 | 405 | uint32_t blocks2Send; |
Just4pLeisure | 4:682d96ff6d79 | 406 | fseek(fp,0x020140,SEEK_SET); |
Just4pLeisure | 5:1775b4b13232 | 407 | if (!fread(&blocks2Send,4,1,fp)) { |
Just4pLeisure | 5:1775b4b13232 | 408 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 409 | return TERM_ERR; |
Just4pLeisure | 5:1775b4b13232 | 410 | } |
Just4pLeisure | 4:682d96ff6d79 | 411 | blocks2Send = (blocks2Send >> 24) | ((blocks2Send << 8) & 0x00FF0000) | ((blocks2Send >> 8) & 0x0000FF00) | (blocks2Send << 24); |
Just4pLeisure | 4:682d96ff6d79 | 412 | printf("Start address of BIN file's Footer area = 0x%06X\r\n", blocks2Send ); |
Just4pLeisure | 4:682d96ff6d79 | 413 | blocks2Send += 0x200; // Add some bytes for the Footer itself and to account for division rounded down later |
Just4pLeisure | 4:682d96ff6d79 | 414 | blocks2Send -= 0x020000; // Remove 0x020000 because we don't send the bootblock and adaptation blocks |
Just4pLeisure | 4:682d96ff6d79 | 415 | printf("Amount of data to send BIN file adjusted for footer = 0x%06X Bytes\r\n", blocks2Send ); |
Just4pLeisure | 4:682d96ff6d79 | 416 | blocks2Send /= 0xE0; |
Just4pLeisure | 4:682d96ff6d79 | 417 | printf("Number of Blocks of 0xE0 Bytes needed to send BIN file = 0x%04X\r\n", blocks2Send ); |
Just4pLeisure | 4:682d96ff6d79 | 418 | // Move BIN file pointer to start of data |
Just4pLeisure | 4:682d96ff6d79 | 419 | fseek (fp , 0x020000 , SEEK_SET); |
Just4pLeisure | 4:682d96ff6d79 | 420 | // Erase the FLASH |
Just4pLeisure | 4:682d96ff6d79 | 421 | printf("Waiting for FLASH to be Erased\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 422 | if (!GMLANRequestDownload(T8REQID, T8RESPID, GMLANRequestDownloadModeEncrypted)) { |
Just4pLeisure | 5:1775b4b13232 | 423 | fclose(fp); |
Just4pLeisure | 4:682d96ff6d79 | 424 | printf("Unable to erase the FLASH chip!\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 425 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 426 | } |
Just4pLeisure | 4:682d96ff6d79 | 427 | // Now send the BIN file |
Just4pLeisure | 5:1775b4b13232 | 428 | GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 429 | TesterPresent.start(); |
Just4pLeisure | 4:682d96ff6d79 | 430 | printf("Sending FLASH BIN file\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 431 | printf(" 0.00 %% complete.\r"); |
Just4pLeisure | 4:682d96ff6d79 | 432 | for (i=0; i<blocks2Send; i++) { |
Just4pLeisure | 4:682d96ff6d79 | 433 | // get a block of 0xE0 bytes in an array called data2Send |
Just4pLeisure | 5:1775b4b13232 | 434 | if (!fread(data2Send,0xE0,1,fp)) { |
Just4pLeisure | 5:1775b4b13232 | 435 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 436 | printf("\r\nError reading the BIN file MODIFIED.BIN\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 437 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 438 | } |
Just4pLeisure | 5:1775b4b13232 | 439 | // encrypt data2Send array by XORing with 6 different values in a ring (modulo function) |
Just4pLeisure | 5:1775b4b13232 | 440 | char key[6] = { 0x39, 0x68, 0x77, 0x6D, 0x47, 0x39 }; |
Just4pLeisure | 5:1775b4b13232 | 441 | for ( j = 0; j < 0xE0; j++ ) |
Just4pLeisure | 5:1775b4b13232 | 442 | data2Send[j] ^= key[(((0xE0*i)+j) % 6)]; |
Just4pLeisure | 4:682d96ff6d79 | 443 | // Send the block of data |
Just4pLeisure | 5:1775b4b13232 | 444 | if (!GMLANDataTransferFirstFrame(T8REQID, T8RESPID, 0xE6, GMLANDOWNLOAD, StartAddress)) { |
Just4pLeisure | 4:682d96ff6d79 | 445 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 446 | printf("\r\nUnable to start BIN File Upload\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 447 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 448 | } |
Just4pLeisure | 4:682d96ff6d79 | 449 | // Send 0x20 messages of 0x07 bytes each (0x20 * 0x07 = 0xE0) |
Just4pLeisure | 4:682d96ff6d79 | 450 | txpnt = 0; |
Just4pLeisure | 4:682d96ff6d79 | 451 | iFrameNumber = 0x21; |
Just4pLeisure | 4:682d96ff6d79 | 452 | for (j=0; j < 0x20; j++) { |
Just4pLeisure | 4:682d96ff6d79 | 453 | GMLANMsg[0] = iFrameNumber; |
Just4pLeisure | 4:682d96ff6d79 | 454 | for (k=1; k<8; k++) |
Just4pLeisure | 4:682d96ff6d79 | 455 | GMLANMsg[k] = data2Send[txpnt++]; |
Just4pLeisure | 5:1775b4b13232 | 456 | if (!can_send_timeout(T8REQID, GMLANMsg, 8, GMLANPTCT)) { |
Just4pLeisure | 4:682d96ff6d79 | 457 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 458 | printf("\r\nUnable to send BIN File\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 459 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 460 | } |
Just4pLeisure | 4:682d96ff6d79 | 461 | ++iFrameNumber &= 0x2F; |
Just4pLeisure | 5:1775b4b13232 | 462 | wait_us(1000); // can be as low as 250 for an ECU on its own, but need 1000 (1ms) to work in a car (use a longer delay to be ultrasafe??? ) |
Just4pLeisure | 4:682d96ff6d79 | 463 | } |
Just4pLeisure | 5:1775b4b13232 | 464 | if (!GMLANDataTransferBlockAcknowledge(T8RESPID)) { |
Just4pLeisure | 4:682d96ff6d79 | 465 | fclose(fp); |
Just4pLeisure | 4:682d96ff6d79 | 466 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 467 | } |
Just4pLeisure | 4:682d96ff6d79 | 468 | if (TesterPresent.read_ms() > 2000) { |
Just4pLeisure | 5:1775b4b13232 | 469 | GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 4:682d96ff6d79 | 470 | TesterPresent.reset(); |
Just4pLeisure | 4:682d96ff6d79 | 471 | } |
Just4pLeisure | 4:682d96ff6d79 | 472 | StartAddress += 0xE0; |
Just4pLeisure | 4:682d96ff6d79 | 473 | printf("%6.2f\r", (100.0*(float)i)/(float)(blocks2Send) ); |
Just4pLeisure | 4:682d96ff6d79 | 474 | } |
Just4pLeisure | 4:682d96ff6d79 | 475 | // FLASHing complete |
Just4pLeisure | 4:682d96ff6d79 | 476 | printf("%6.2f\r\n", (float)100 ); |
Just4pLeisure | 4:682d96ff6d79 | 477 | // End programming session and return to normal mode |
Just4pLeisure | 5:1775b4b13232 | 478 | if (!GMLANReturnToNormalMode(T8REQID, T8RESPID)) { |
Just4pLeisure | 4:682d96ff6d79 | 479 | fclose(fp); |
Just4pLeisure | 4:682d96ff6d79 | 480 | printf("UH-OH! T8 ECU did not Return To Normal Mode!!\r\n"); |
Just4pLeisure | 4:682d96ff6d79 | 481 | return FALSE; |
Just4pLeisure | 4:682d96ff6d79 | 482 | } |
Just4pLeisure | 4:682d96ff6d79 | 483 | timer.stop(); |
Just4pLeisure | 4:682d96ff6d79 | 484 | printf("SUCCESS! FLASHing the BIN file took %#.1f seconds.\r\n",timer.read()); |
Just4pLeisure | 4:682d96ff6d79 | 485 | fclose(fp); |
Just4pLeisure | 4:682d96ff6d79 | 486 | return TRUE; |
Just4pLeisure | 4:682d96ff6d79 | 487 | } |
Just4pLeisure | 5:1775b4b13232 | 488 | |
Just4pLeisure | 5:1775b4b13232 | 489 | bool t8_recover() |
Just4pLeisure | 5:1775b4b13232 | 490 | { |
Just4pLeisure | 5:1775b4b13232 | 491 | uint32_t i = 0, j = 0, k = 0; |
Just4pLeisure | 5:1775b4b13232 | 492 | |
Just4pLeisure | 5:1775b4b13232 | 493 | timer.reset(); |
Just4pLeisure | 5:1775b4b13232 | 494 | timer.start(); |
Just4pLeisure | 5:1775b4b13232 | 495 | printf("Recovering your T8 ECU ...\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 496 | // |
Just4pLeisure | 5:1775b4b13232 | 497 | if (!GMLANprogrammingSetupProcess(T8USDTREQID, T8UUDTRESPID)) |
Just4pLeisure | 5:1775b4b13232 | 498 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 499 | // |
Just4pLeisure | 5:1775b4b13232 | 500 | printf("Requesting Security Access\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 501 | if (!t8_authenticate(T8USDTREQID, T8UUDTRESPID, 0x01)) { |
Just4pLeisure | 5:1775b4b13232 | 502 | printf("Unable to get Security Access\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 503 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 504 | } |
Just4pLeisure | 5:1775b4b13232 | 505 | printf("Security Access Granted\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 506 | // |
Just4pLeisure | 5:1775b4b13232 | 507 | // const uint8_t BootLoader[] = T8BootloaderProg; |
Just4pLeisure | 5:1775b4b13232 | 508 | // if(!GMLANprogrammingUtilityFileProcess(T8USDTREQID, T8UUDTRESPID, BootLoader)) |
Just4pLeisure | 5:1775b4b13232 | 509 | if(!GMLANprogrammingUtilityFileProcess(T8USDTREQID, T8UUDTRESPID, T8BootLoaderWrite)) |
Just4pLeisure | 5:1775b4b13232 | 510 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 511 | // |
Just4pLeisure | 5:1775b4b13232 | 512 | |
Just4pLeisure | 5:1775b4b13232 | 513 | |
Just4pLeisure | 5:1775b4b13232 | 514 | // All steps needed to transfer and start a bootloader ('Utility File' in GMLAN parlance) |
Just4pLeisure | 5:1775b4b13232 | 515 | uint32_t StartAddress = 0x020000; |
Just4pLeisure | 5:1775b4b13232 | 516 | uint32_t txpnt = 0; |
Just4pLeisure | 5:1775b4b13232 | 517 | char iFrameNumber = 0x21; |
Just4pLeisure | 5:1775b4b13232 | 518 | char GMLANMsg[8]; |
Just4pLeisure | 5:1775b4b13232 | 519 | char data2Send[0xE0]; |
Just4pLeisure | 5:1775b4b13232 | 520 | // |
Just4pLeisure | 5:1775b4b13232 | 521 | // fopen modified.bin here, check it is OK and work out how much data I need to send |
Just4pLeisure | 5:1775b4b13232 | 522 | // need lots of fcloses though |
Just4pLeisure | 5:1775b4b13232 | 523 | printf("Checking the FLASH BIN file...\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 524 | FILE *fp = fopen("/local/modified.bin", "r"); // Open "modified.bin" on the local file system for reading |
Just4pLeisure | 5:1775b4b13232 | 525 | if (!fp) { |
Just4pLeisure | 5:1775b4b13232 | 526 | printf("Error: I could not find the BIN file MODIFIED.BIN\r\n");; |
Just4pLeisure | 5:1775b4b13232 | 527 | return TERM_ERR; |
Just4pLeisure | 5:1775b4b13232 | 528 | } |
Just4pLeisure | 5:1775b4b13232 | 529 | // obtain file size - it should match the size of the FLASH chips: |
Just4pLeisure | 5:1775b4b13232 | 530 | fseek (fp , 0 , SEEK_END); |
Just4pLeisure | 5:1775b4b13232 | 531 | uint32_t file_size = ftell (fp); |
Just4pLeisure | 5:1775b4b13232 | 532 | rewind (fp); |
Just4pLeisure | 5:1775b4b13232 | 533 | |
Just4pLeisure | 5:1775b4b13232 | 534 | // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU |
Just4pLeisure | 5:1775b4b13232 | 535 | uint32_t stack_long = 0; |
Just4pLeisure | 5:1775b4b13232 | 536 | if (!fread(&stack_long,4,1,fp)) { |
Just4pLeisure | 5:1775b4b13232 | 537 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 538 | return TERM_ERR; |
Just4pLeisure | 5:1775b4b13232 | 539 | } |
Just4pLeisure | 5:1775b4b13232 | 540 | stack_long = (stack_long >> 24) | ((stack_long << 8) & 0x00FF0000) | ((stack_long >> 8) & 0x0000FF00) | (stack_long << 24); |
Just4pLeisure | 5:1775b4b13232 | 541 | // |
Just4pLeisure | 5:1775b4b13232 | 542 | if (file_size != T8FLASHSIZE || stack_long != T8POINTER) { |
Just4pLeisure | 5:1775b4b13232 | 543 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 544 | printf("The BIN file does not appear to be for a T8 ECU :-(\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 545 | printf("BIN file size: %#010x, FLASH chip size: %#010x, Pointer: %#010x.\r\n", file_size, T7FLASHSIZE, stack_long); |
Just4pLeisure | 5:1775b4b13232 | 546 | return TERM_ERR; |
Just4pLeisure | 5:1775b4b13232 | 547 | } |
Just4pLeisure | 5:1775b4b13232 | 548 | // It is possible to save some time by only sending the program code and CAL data |
Just4pLeisure | 5:1775b4b13232 | 549 | // This is just a rough calculation, and slight overestimate of the number of blocks of data needed to send the BIN file |
Just4pLeisure | 5:1775b4b13232 | 550 | uint32_t blocks2Send; |
Just4pLeisure | 5:1775b4b13232 | 551 | fseek(fp,0x020140,SEEK_SET); |
Just4pLeisure | 5:1775b4b13232 | 552 | if (!fread(&blocks2Send,4,1,fp)) { |
Just4pLeisure | 5:1775b4b13232 | 553 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 554 | return TERM_ERR; |
Just4pLeisure | 5:1775b4b13232 | 555 | } |
Just4pLeisure | 5:1775b4b13232 | 556 | blocks2Send = (blocks2Send >> 24) | ((blocks2Send << 8) & 0x00FF0000) | ((blocks2Send >> 8) & 0x0000FF00) | (blocks2Send << 24); |
Just4pLeisure | 5:1775b4b13232 | 557 | printf("Start address of BIN file's Footer area = 0x%06X\r\n", blocks2Send ); |
Just4pLeisure | 5:1775b4b13232 | 558 | blocks2Send += 0x200; // Add some bytes for the Footer itself and to account for division rounded down later |
Just4pLeisure | 5:1775b4b13232 | 559 | blocks2Send -= 0x020000; // Remove 0x020000 because we don't send the bootblock and adaptation blocks |
Just4pLeisure | 5:1775b4b13232 | 560 | printf("Amount of data to send BIN file adjusted for footer = 0x%06X Bytes\r\n", blocks2Send ); |
Just4pLeisure | 5:1775b4b13232 | 561 | blocks2Send /= 0xE0; |
Just4pLeisure | 5:1775b4b13232 | 562 | printf("Number of Blocks of 0xE0 Bytes needed to send BIN file = 0x%04X\r\n", blocks2Send ); |
Just4pLeisure | 5:1775b4b13232 | 563 | // Move BIN file pointer to start of data |
Just4pLeisure | 5:1775b4b13232 | 564 | fseek (fp , 0x020000 , SEEK_SET); |
Just4pLeisure | 5:1775b4b13232 | 565 | // Erase the FLASH |
Just4pLeisure | 5:1775b4b13232 | 566 | printf("Waiting for FLASH to be Erased\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 567 | if (!GMLANRequestDownload(T8REQID, T8RESPID, GMLANRequestDownloadModeEncrypted)) { |
Just4pLeisure | 5:1775b4b13232 | 568 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 569 | printf("Unable to erase the FLASH chip!\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 570 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 571 | } |
Just4pLeisure | 5:1775b4b13232 | 572 | // Now send the BIN file |
Just4pLeisure | 5:1775b4b13232 | 573 | GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 5:1775b4b13232 | 574 | TesterPresent.start(); |
Just4pLeisure | 5:1775b4b13232 | 575 | printf("Sending FLASH BIN file\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 576 | printf(" 0.00 %% complete.\r"); |
Just4pLeisure | 5:1775b4b13232 | 577 | for (i=0; i<blocks2Send; i++) { |
Just4pLeisure | 5:1775b4b13232 | 578 | // get a block of 0xE0 bytes in an array called data2Send |
Just4pLeisure | 5:1775b4b13232 | 579 | if (!fread(data2Send,0xE0,1,fp)) { |
Just4pLeisure | 5:1775b4b13232 | 580 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 581 | printf("\r\nError reading the BIN file MODIFIED.BIN\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 582 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 583 | } |
Just4pLeisure | 5:1775b4b13232 | 584 | // encrypt data2Send array by XORing with 6 different values in a ring (modulo function) |
Just4pLeisure | 5:1775b4b13232 | 585 | char key[6] = { 0x39, 0x68, 0x77, 0x6D, 0x47, 0x39 }; |
Just4pLeisure | 5:1775b4b13232 | 586 | for ( j = 0; j < 0xE0; j++ ) |
Just4pLeisure | 5:1775b4b13232 | 587 | data2Send[j] ^= key[(((0xE0*i)+j) % 6)]; |
Just4pLeisure | 5:1775b4b13232 | 588 | // Send the block of data |
Just4pLeisure | 5:1775b4b13232 | 589 | if (!GMLANDataTransferFirstFrame(T8REQID, T8RESPID, 0xE6, GMLANDOWNLOAD, StartAddress)) { |
Just4pLeisure | 5:1775b4b13232 | 590 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 591 | printf("\r\nUnable to start BIN File Upload\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 592 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 593 | } |
Just4pLeisure | 5:1775b4b13232 | 594 | // Send 0x20 messages of 0x07 bytes each (0x20 * 0x07 = 0xE0) |
Just4pLeisure | 5:1775b4b13232 | 595 | txpnt = 0; |
Just4pLeisure | 5:1775b4b13232 | 596 | iFrameNumber = 0x21; |
Just4pLeisure | 5:1775b4b13232 | 597 | for (j=0; j < 0x20; j++) { |
Just4pLeisure | 5:1775b4b13232 | 598 | GMLANMsg[0] = iFrameNumber; |
Just4pLeisure | 5:1775b4b13232 | 599 | for (k=1; k<8; k++) |
Just4pLeisure | 5:1775b4b13232 | 600 | GMLANMsg[k] = data2Send[txpnt++]; |
Just4pLeisure | 5:1775b4b13232 | 601 | if (!can_send_timeout(T8REQID, GMLANMsg, 8, GMLANPTCT)) { |
Just4pLeisure | 5:1775b4b13232 | 602 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 603 | printf("\r\nUnable to send BIN File\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 604 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 605 | } |
Just4pLeisure | 5:1775b4b13232 | 606 | ++iFrameNumber &= 0x2F; |
Just4pLeisure | 5:1775b4b13232 | 607 | wait_us(1000); // was 250 use 1000 or wait_ms(1) to be ultrasafe |
Just4pLeisure | 5:1775b4b13232 | 608 | } |
Just4pLeisure | 5:1775b4b13232 | 609 | if (!GMLANDataTransferBlockAcknowledge(T8RESPID)) { |
Just4pLeisure | 5:1775b4b13232 | 610 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 611 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 612 | } |
Just4pLeisure | 5:1775b4b13232 | 613 | if (TesterPresent.read_ms() > 2000) { |
Just4pLeisure | 5:1775b4b13232 | 614 | GMLANTesterPresent(T8REQID, T8RESPID); |
Just4pLeisure | 5:1775b4b13232 | 615 | TesterPresent.reset(); |
Just4pLeisure | 5:1775b4b13232 | 616 | } |
Just4pLeisure | 5:1775b4b13232 | 617 | StartAddress += 0xE0; |
Just4pLeisure | 5:1775b4b13232 | 618 | printf("%6.2f\r", (100.0*(float)i)/(float)(blocks2Send) ); |
Just4pLeisure | 5:1775b4b13232 | 619 | } |
Just4pLeisure | 5:1775b4b13232 | 620 | // FLASHing complete |
Just4pLeisure | 5:1775b4b13232 | 621 | printf("%6.2f\r\n", (float)100 ); |
Just4pLeisure | 5:1775b4b13232 | 622 | // End programming session and return to normal mode |
Just4pLeisure | 5:1775b4b13232 | 623 | if (!GMLANReturnToNormalMode(T8REQID, T8RESPID)) { |
Just4pLeisure | 5:1775b4b13232 | 624 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 625 | printf("UH-OH! T8 ECU did not Return To Normal Mode!!\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 626 | return FALSE; |
Just4pLeisure | 5:1775b4b13232 | 627 | } |
Just4pLeisure | 5:1775b4b13232 | 628 | timer.stop(); |
Just4pLeisure | 5:1775b4b13232 | 629 | fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 630 | printf("SUCCESS: Your T8 ECU has been recovered.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 631 | return TRUE; |
Just4pLeisure | 5:1775b4b13232 | 632 | } |