Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Diff: t7utils.cpp
- Revision:
- 3:92dae9083c83
- Child:
- 4:682d96ff6d79
diff -r bf3a2b29259a -r 92dae9083c83 t7utils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/t7utils.cpp Tue Jun 07 12:23:28 2011 +0000 @@ -0,0 +1,580 @@ +/******************************************************************************* + +t7utils.cpp +(c) 2011 by Sophie Dexter +portions (c) Tomi Liljemark (firstname.surname@gmail.com) + +This C++ module provides functions for communicating simple messages to and from +the T7 ECU + +******************************************************************************** + +WARNING: Use at your own risk, sadly this software comes with no guarantees. +This software is provided 'free' and in good faith, but the author does not +accept liability for any damage arising from its use. + +*******************************************************************************/ + +#include "t7utils.h" + + +// +// t7_initialise +// +// sends an initialisation message to the T7 ECU +// but doesn't displays anything. +// +// inputs: none +// return: bool TRUE if there was a message, FALSE if no message. +// + + +bool t7_initialise() { + // send a can message to the T7 requesting that it initialises CAN communication with Just4Trionic + char T7TxMsg[] = T7INITMSG; + if (!can_send_timeout (T7CMNDID, T7TxMsg, 8, T7MESSAGETIMEOUT)) + return FALSE; + // wait for the T7 to reply + char T7RxMsg[8]; + // if a message is not received, has the wrong id + if (!can_wait_timeout(T7RESPID, T7RxMsg, 8, T7MESSAGETIMEOUT)) + return FALSE; + /* DEBUG info... + for (int i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] ); + printf(" init\r\n"); + */ + return TRUE; +} + +// +// t7_authenticate +// +// sends an authentication message to the T7 ECU +// but doesn't displays anything. +// +// inputs: none +// return: bool TRUE if there was a message, FALSE if no message. +// + +bool t7_authenticate() { + uint16_t seed, key; +// uint16_t i; + char T7TxAck[] = T7ACK_MSG; + char T7TxMsg[] = T7SEC_MSG; + char T7TxKey[] = T7KEY_MSG; + char T7RxMsg[8]; + // Send "Request Seed" to Trionic7 + if (!can_send_timeout (T7SEC_ID, T7TxMsg, 8, T7MESSAGETIMEOUT)) + return FALSE; + // wait for the T7 to reply + // Read "Seed" + // if a message is not received id return false + if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) + return FALSE; + /* DEBUG info... + for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] ); + printf(" seed\r\n"); + */ + // Send Ack + T7TxAck[3] = T7RxMsg[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7TxAck, 8, T7MESSAGETIMEOUT)) + return FALSE; + // Send "Key", try two different methods of calculating the key + seed = T7RxMsg[5] << 8 | T7RxMsg[6]; + for (int method = 0; method < 2; method++ ) { + key = seed << 2; + key &= 0xFFFF; + key ^= ( method ? 0x4081 : 0x8142 ); + key -= ( method ? 0x1F6F : 0x2356 ); + key &= 0xFFFF; + T7TxKey[5] = ( key >> 8 ) & 0xFF; + T7TxKey[6] = key & 0xFF; + if (!can_send_timeout (T7SEC_ID, T7TxKey, 8, T7MESSAGETIMEOUT)) + return FALSE; + // Wait for response + // if a message is not received id return false + if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) + return FALSE; + /* DEBUG info... + for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] ); + printf(" key %d 0x%02X 0x%02X\r\n", method, T7RxMsg[3], T7RxMsg[5]); + */ + // Send Ack + T7TxAck[3] = T7RxMsg[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7TxAck, 8, T7MESSAGETIMEOUT)) { + /* DEBUG info... + printf("Key ACK message timeout\r\n"); + */ + return FALSE; + } + if ( T7RxMsg[3] == 0x67 && T7RxMsg[5] == 0x34 ) { + /* DEBUG info... + printf("Key %d Accepted\r\n", method); + */ + return TRUE; + } else { + /* DEBUG info... + printf("Key %d Failed\r\n", method); + */ + } + } + return FALSE; +} +// +// t7_dump +// +// dumps the T7 BIN File +// but doesn't displays anything. +// +// inputs: none +// return: bool TRUE if there was a message, FALSE if no message. +// + +bool t7_dump() { + uint32_t received; + uint8_t byte_count, retries, i; + char T7_dump_jumpa[] = T7DMPJP1A; + char T7_dump_jumpb[] = T7DMPJP1B; + char T7_dump_ack[] = T7DMP_ACK; + char T7_dump_data[] = T7DMPDATA; + char T7_dump_end[] = T7DMP_END; + char T7RxMsg[8]; + + printf("Creating FLASH dump file...\r\n"); + FILE *fp = fopen("/local/original.bin", "w"); // Open "original.bin" on the local file system for writing + if (!fp) { + perror ("The following error occured"); + return TERM_ERR; + } + + timer.reset(); + timer.start(); + + received = 0; + printf(" %% complete.\r"); + while (received < T7FLASHSIZE) { +// T7_dump_jumpa[7] = ((T7FLASHSIZE - received) < 0xEF) ? (T7FLASHSIZE - received) : 0xEF; + T7_dump_jumpb[2] = (received >> 16) & 0xFF; + T7_dump_jumpb[3] = (received >> 8) & 0xFF; + T7_dump_jumpb[4] = received & 0xFF; + // Send read address and length to Trionic + if (!can_send_timeout (T7SEC_ID, T7_dump_jumpa, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (!can_send_timeout (T7SEC_ID, T7_dump_jumpb, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + // Wait for a response + if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + /* DEBUG info... + for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] ); + printf(" seed\r\n"); + */ + // Send Ack + T7_dump_ack[3] = T7RxMsg[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) { + printf("ERROR Asking1: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if ((T7RxMsg[3] != 0x6C) ||(T7RxMsg[4] != 0xF0)) { + printf("ERROR Asking2: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + // Ask T7 ECU to start sending data + for (retries = 0 ; retries <10 ; retries++ ) { + if (!can_send_timeout (T7SEC_ID, T7_dump_data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + // Read mesages from the T7 ECU + byte_count = 0; + T7RxMsg[0] = 0x00; + while (T7RxMsg[0] != 0x80 && T7RxMsg[0] != 0xC0) { + if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) + break; + // Need to process the received data here! + // Send Ack + T7_dump_ack[3] = T7RxMsg[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) { + printf("ERROR processing: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } +// /* DEBUG info... +// for (i = 0; i < 8; i++ ) printf("0x%02X ", T7RxMsg[i] ); +// for (i = 2; i < 8; i++ ) printf("%c ", T7RxMsg[i] ); +// printf(" data\r\n"); + for (i = 2; i < 8; i++ ) + file_buffer[byte_count++] = (T7RxMsg[i]); +// */ + } + // Success if these conditions met + if (T7RxMsg[0] == 0x80 || T7RxMsg[0] == 0xC0) + break; +// printf("retries: %d\r\n", retries); + } + if (retries > 9) { + printf("err t7utils line: %d\r\n", __LINE__ ); + printf("Retries: %d, Done: %5.2f %%\r\n", retries, 100*(float)received/(float)T7FLASHSIZE ); + fclose(fp); + return FALSE; + } +// received += 0xEF; + received += 0x80; +// printf("Retries: %d, Done: %5.2f %%\r\n", retries, 100*(float)received/(float)T7FLASHSIZE ); + printf("%6.2f\r", 100*(float)received/(float)T7FLASHSIZE ); + fwrite((file_buffer + 3), 1, 0x80, fp); + if (ferror (fp)) { + fclose (fp); + printf ("Error writing to the FLASH BIN file.\r\n"); + return TERM_ERR; + } + } + printf("\n"); + // Send Message to T7 ECU to say that we have finished + if (!can_send_timeout (T7SEC_ID, T7_dump_end, 8, T7MESSAGETIMEOUT)) { + fclose(fp); + return FALSE; + } + // Wait for response + if (!can_wait_timeout(T7SEC_RX, T7RxMsg, 8, T7MESSAGETIMEOUT)) { + fclose(fp); + return FALSE; + } +// Send Ack + T7_dump_ack[3] = T7RxMsg[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_dump_ack, 8, T7MESSAGETIMEOUT)) { + printf("ERROR closing1: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (T7RxMsg[3] != 0xC2) { + printf("ERROR closing2: %5.1f %% done\r\n", 100*(float)received/(float)T7FLASHSIZE); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + timer.stop(); + printf("SUCCESS! Getting the FLASH dump took %#.1f seconds.\r\n",timer.read()); + fclose(fp); + return TRUE; +} + +bool t7_erase() { + char T7_erase_msga[] = { 0x40, 0xA1, 0x02, 0x31, 0x52, 0x00, 0x00, 0x00 }; + char T7_erase_msgb[] = { 0x40, 0xA1, 0x02, 0x31, 0x53, 0x00, 0x00, 0x00 }; + char T7_erase_confirm[] = { 0x40, 0xA1, 0x01, 0x3E, 0x00, 0x00, 0x00, 0x00 }; + char T7_erase_ack[] = { 0x40, 0xA1, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00 }; + char data[8]; + int i; + + printf("Erasing T7 ECU FLASH...\r\n"); + + data[3] = 0; + i = 0; + while ( data[3] != 0x71 && i < 10) { + // Send "Request to ERASE" to Trionic + if (!can_send_timeout (T7SEC_ID, T7_erase_msga, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + T7_erase_ack[3] = data[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_erase_ack, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + wait_ms(100); + i++; + printf("."); + } + printf("\r\n"); + // Check to see if erase operation lasted longer than 1 sec... + if (i >=10) { + printf("Second Message took too long'\r\n"); + return FALSE; + } + data[3] = 0; + i = 0; + while ( data[3] != 0x71 && i < 200) { + // Send "Request to ERASE" to Trionic + if (!can_send_timeout (T7SEC_ID, T7_erase_msgb, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + T7_erase_ack[3] = data[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_erase_ack, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + wait_ms(100); + i++; + printf("."); + } + printf("\r\n"); + // Check to see if erase operation lasted longer than 20 sec... + if (i >=200) { + printf("Second Message took too long'\r\n"); + return FALSE; + } + + // Confirm erase was successful? + // (Note: no acknowledgements used for some reason) + if (!can_send_timeout (T7SEC_ID, T7_erase_confirm, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + if ( data[3] != 0x7E ) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + wait_ms(100); + if (!can_send_timeout (T7SEC_ID, T7_erase_confirm, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + if ( data[3] != 0x7E ) { + printf("err t7utils line: %d\r\n", __LINE__ ); + return FALSE; + } + printf("SUCCESS: The FLASH has been erased.\r\n"); + return TRUE; +} + +bool t7_flash() { + char T7_flash_jumpa[] = T7FLAJP1A; + char T7_flash_jumpb[] = T7FLAJP1B; + char T7_flash_end[] = T7FLA_END; + char T7_flash_exit[] = T7FLAEXIT; + char T7_flash_ack[] = T7FLA_ACK; + char data[8]; + int i, k; + + // fopen modified.hex here? + // need lots of fcloses though + printf("Checking the FLASH BIN file...\r\n"); + FILE *fp = fopen("/local/modified.hex", "r"); // Open "modified.hex" on the local file system for reading + if (!fp) { + printf("Error: I could not find the BIN file MODIFIED.HEX\r\n");; + return TERM_ERR; + } + // obtain file size - it should match the size of the FLASH chips: + fseek (fp , 0 , SEEK_END); + uint32_t file_size = ftell (fp); + rewind (fp); + + // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU + uint8_t stack_byte = 0; + uint32_t stack_long = 0; + if (!fread(&stack_byte,1,1,fp)) return TERM_ERR; + stack_long |= (stack_byte << 24); + if (!fread(&stack_byte,1,1,fp)) return TERM_ERR; + stack_long |= (stack_byte << 16); + if (!fread(&stack_byte,1,1,fp)) return TERM_ERR; + stack_long |= (stack_byte << 8); + if (!fread(&stack_byte,1,1,fp)) return TERM_ERR; + stack_long |= stack_byte; + rewind (fp); + + if (file_size != T7FLASHSIZE || stack_long != T7POINTER) { + fclose(fp); + printf("The BIN file does not appear to be for a T7 ECU :-(\r\n"); + printf("BIN file size: %#010x, FLASH chip size: %#010x, Pointer: %#010x.\r\n", file_size, T7FLASHSIZE, stack_long); + return TERM_ERR; + } + + timer.reset(); + timer.start(); + + // Send "Request Download - tool to module" to Trionic + if (!can_send_timeout (T7SEC_ID, T7_flash_jumpa, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (!can_send_timeout (T7SEC_ID, T7_flash_jumpb, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + T7_flash_ack[3] = data[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if ( data[3] != 0x74 ) { + printf("Cannot Update FLASH, message refused.\r\n"); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + + uint32_t address = 0; + + printf(" %% complete.\r"); + while (address < T7FLASHSIZE) { + + data[0] = 0x4A; // 0x40 send, | 0x0A (10) messages to follow +// data[0] = 0x42; // 0x40 send, | 0x02 (2) messages to follow +// data[0] = 0x40; // 0x40 send, | 0x00 (0) messages to follow + data[1] = 0xA1; + data[2] = 0x41; // length+1 (64 Bytes) +// data[2] = 0x11; // length+1 (16 Bytes) +// data[2] = 0x05; // length+1 (4 Bytes) + data[3] = 0x36; // Data Transfer + for ( k = 4; k < 8; k++ ) + //data[k] = *(bin + bin_count++); + if (!fread(&data[k],1,1,fp)) { + fclose(fp); + printf("Error reading the BIN file MODIFIED.HEX"); + return FALSE; + } +// /* DEBUG info... +// for (k = 0; k < 8; k++ ) printf("0x%02X ", data[k] ); +// for (k = 2; k < 8; k++ ) printf("%c ", data[k] ); +// printf(" data\r\n"); + + if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } +//* + for (i = 9; i>=0; i--) { +// for (i = 1; i>=0; i--) { + data[0] = i; + // data[1] = 0xA1; + for ( k = 2; k < 8; k++ ) + //data[k] = *(bin + bin_count++); + if (!fread(&data[k],1,1,fp)) { + fclose(fp); + printf("Error reading the BIN file MODIFIED.HEX"); + return FALSE; + } +// /* DEBUG info... +// for (k = 0; k < 8; k++ ) printf("0x%02X ", data[k] ); +// for (k = 2; k < 8; k++ ) printf("%c ", data[k] ); +// printf(" data\r\n"); + +// printf("%6.2f\r", 100*(float)address/(float)T7FLASHSIZE ); + wait_ms(1); + if (!can_send_timeout (T7SEC_ID, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + } +//*/ + address += 0x40; +// address += 0x10; +// address += 0x04; + if (!can_wait_timeout(T7SEC_RX, data, 8, T7LONGERTIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + // Send acknowledgement + T7_flash_ack[3] = data[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if ( data[3] != 0x76 ) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (!(address % 0x80)) + printf("%6.2f\r", 100*(float)address/(float)T7FLASHSIZE ); + } + printf("\n"); +/* + // Send "Request Data Transfer Exit" to Trionic + if (!can_send_timeout (T7SEC_ID, T7_flash_end, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + T7_flash_ack[3] = data[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if ( data[3] != 0x77 ) { + printf("Cannot Update FLASH, message refused.\r\n"); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + // Send "Request Data Transfer Exit" to Trionic + if (!can_send_timeout (T7SEC_ID, T7_flash_exit, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if (!can_wait_timeout(T7SEC_RX, data, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + T7_flash_ack[3] = data[0] & 0xBF; + if (!can_send_timeout (T7ACK_ID, T7_flash_ack, 8, T7MESSAGETIMEOUT)) { + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } + if ( data[3] != 0x71 ) { + printf("Cannot Update FLASH, message refused.\r\n"); + printf("err t7utils line: %d\r\n", __LINE__ ); + fclose(fp); + return FALSE; + } +*/ + timer.stop(); + printf("SUCCESS! Programming the FLASH took %#.1f seconds.\r\n",timer.read()); + fclose(fp); + return TRUE; +} \ No newline at end of file