Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Committer:
Just4pLeisure
Date:
Tue Jun 07 12:23:28 2011 +0000
Revision:
3:92dae9083c83
Parent:
2:bf3a2b29259a
Child:
4:682d96ff6d79
Basic T7 CAN DUMP and FLASH for P-BUS connection only
Requires MyBooty V2.x for T5 CAN FLASHing at 1 Mbps

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Just4pLeisure 1:d5452e398b76 1 /*******************************************************************************
Just4pLeisure 1:d5452e398b76 2
Just4pLeisure 1:d5452e398b76 3 bdmtrionic.cpp
Just4pLeisure 1:d5452e398b76 4 (c) 2010 by Sophie Dexter
Just4pLeisure 1:d5452e398b76 5
Just4pLeisure 1:d5452e398b76 6 General purpose BDM functions for Just4Trionic by Just4pLeisure
Just4pLeisure 1:d5452e398b76 7
Just4pLeisure 1:d5452e398b76 8 A derivative work based on:
Just4pLeisure 1:d5452e398b76 9 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 10 // CAN/BDM adapter firmware
Just4pLeisure 1:d5452e398b76 11 // (C) Janis Silins, 2010
Just4pLeisure 1:d5452e398b76 12 // $id$
Just4pLeisure 1:d5452e398b76 13 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 14
Just4pLeisure 1:d5452e398b76 15 ********************************************************************************
Just4pLeisure 1:d5452e398b76 16
Just4pLeisure 1:d5452e398b76 17 WARNING: Use at your own risk, sadly this software comes with no guarantees.
Just4pLeisure 1:d5452e398b76 18 This software is provided 'free' and in good faith, but the author does not
Just4pLeisure 1:d5452e398b76 19 accept liability for any damage arising from its use.
Just4pLeisure 1:d5452e398b76 20
Just4pLeisure 1:d5452e398b76 21 *******************************************************************************/
Just4pLeisure 1:d5452e398b76 22
Just4pLeisure 1:d5452e398b76 23 #include "bdmtrionic.h"
Just4pLeisure 1:d5452e398b76 24
Just4pLeisure 1:d5452e398b76 25 // structure for command address/value pairs
Just4pLeisure 1:d5452e398b76 26 struct mempair_t {
Just4pLeisure 1:d5452e398b76 27 uint32_t addr; ///< target address
Just4pLeisure 1:d5452e398b76 28 uint16_t val; ///< word value
Just4pLeisure 1:d5452e398b76 29 };
Just4pLeisure 1:d5452e398b76 30
Just4pLeisure 1:d5452e398b76 31 // word write algorithm (29Fxxx)
Just4pLeisure 1:d5452e398b76 32 static const struct mempair_t am29_write [] = {
Just4pLeisure 1:d5452e398b76 33 {0xaaaa, 0xaaaa}, {0x5554, 0x5555}, {0xaaaa, 0xa0a0},
Just4pLeisure 1:d5452e398b76 34 };
Just4pLeisure 1:d5452e398b76 35
Just4pLeisure 1:d5452e398b76 36 // chip erase algorithms
Just4pLeisure 1:d5452e398b76 37 static const struct mempair_t am29_erase [] = {
Just4pLeisure 1:d5452e398b76 38 {0xaaaa, 0xaaaa}, {0x5554, 0x5555}, {0xaaaa, 0x8080},
Just4pLeisure 1:d5452e398b76 39 {0xaaaa, 0xaaaa}, {0x5554, 0x5555}, {0xaaaa, 0x1010}
Just4pLeisure 1:d5452e398b76 40 };
Just4pLeisure 1:d5452e398b76 41
Just4pLeisure 1:d5452e398b76 42 // reset algorithms
Just4pLeisure 1:d5452e398b76 43 //static const struct mempair_t am29_reset = {0xfffe, 0xf0f0};
Just4pLeisure 1:d5452e398b76 44 static const struct mempair_t am29_reset [] = {
Just4pLeisure 1:d5452e398b76 45 {0xaaaa, 0xaaaa}, {0x5554, 0x5555}, {0xaaaa, 0xf0f0},
Just4pLeisure 1:d5452e398b76 46 };
Just4pLeisure 1:d5452e398b76 47
Just4pLeisure 1:d5452e398b76 48 // chip id algorithms
Just4pLeisure 1:d5452e398b76 49 static const struct mempair_t am29_id [] = {
Just4pLeisure 1:d5452e398b76 50 {0xaaaa, 0xaaaa}, {0x5554, 0x5555}, {0xaaaa, 0x9090},
Just4pLeisure 1:d5452e398b76 51 };
Just4pLeisure 1:d5452e398b76 52
Just4pLeisure 1:d5452e398b76 53 // ;-)
Just4pLeisure 1:d5452e398b76 54 static const struct mempair_t flash_tag [] = {
Just4pLeisure 1:d5452e398b76 55 {0x7fe00, 0xFF4A}, {0x7fe02, 0x7573}, {0x7fe04, 0x7434}, {0x7fe06, 0x704C},
Just4pLeisure 1:d5452e398b76 56 {0x7fe08, 0x6569}, {0x7fe0a, 0x7375}, {0x7fe0c, 0x7265}, {0x7fe0e, 0x3B29},
Just4pLeisure 1:d5452e398b76 57 };
Just4pLeisure 1:d5452e398b76 58
Just4pLeisure 1:d5452e398b76 59 // local functions
Just4pLeisure 1:d5452e398b76 60 bool reset_am29(void);
Just4pLeisure 1:d5452e398b76 61 bool erase_am29();
Just4pLeisure 1:d5452e398b76 62 bool flash_am29(const uint32_t* addr, uint16_t value);
Just4pLeisure 1:d5452e398b76 63 bool reset_am28(void);
Just4pLeisure 1:d5452e398b76 64 bool erase_am28(const uint32_t* start_addr, const uint32_t* end_addr);
Just4pLeisure 1:d5452e398b76 65 bool flash_am28(const uint32_t* addr, uint16_t value);
Just4pLeisure 1:d5452e398b76 66 bool get_flash_id(uint8_t* make, uint8_t* type);
Just4pLeisure 1:d5452e398b76 67
Just4pLeisure 1:d5452e398b76 68
Just4pLeisure 1:d5452e398b76 69 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 70 /**
Just4pLeisure 1:d5452e398b76 71 Dumps contents of a memory block from [start_addr] up to, but not including,
Just4pLeisure 1:d5452e398b76 72 the [end_addr] as long words (word-aligned addresses). MCU must be in
Just4pLeisure 1:d5452e398b76 73 background mode. The operation interrupts if the break character is
Just4pLeisure 1:d5452e398b76 74 received.
Just4pLeisure 1:d5452e398b76 75
Just4pLeisure 1:d5452e398b76 76 @param start_addr block start address
Just4pLeisure 1:d5452e398b76 77 @param end_addr block end address
Just4pLeisure 1:d5452e398b76 78
Just4pLeisure 1:d5452e398b76 79 @return status flag
Just4pLeisure 1:d5452e398b76 80 */
Just4pLeisure 1:d5452e398b76 81
Just4pLeisure 1:d5452e398b76 82
Just4pLeisure 1:d5452e398b76 83 uint8_t dump_flash(const uint32_t* start_addr, const uint32_t* end_addr) {
Just4pLeisure 1:d5452e398b76 84
Just4pLeisure 1:d5452e398b76 85 // check parametres
Just4pLeisure 1:d5452e398b76 86 if (*start_addr > *end_addr) {
Just4pLeisure 1:d5452e398b76 87 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 88 }
Just4pLeisure 1:d5452e398b76 89
Just4pLeisure 1:d5452e398b76 90 // dump memory contents
Just4pLeisure 1:d5452e398b76 91 uint32_t curr_addr = *start_addr;
Just4pLeisure 1:d5452e398b76 92 uint32_t value;
Just4pLeisure 1:d5452e398b76 93
Just4pLeisure 1:d5452e398b76 94 while ((curr_addr < *end_addr) && (pc.getc() != TERM_BREAK)) {
Just4pLeisure 1:d5452e398b76 95 // read long word
Just4pLeisure 1:d5452e398b76 96 if (curr_addr > *start_addr) {
Just4pLeisure 1:d5452e398b76 97 if (memdump_long(&value) != TERM_OK) {
Just4pLeisure 1:d5452e398b76 98 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 99 }
Just4pLeisure 1:d5452e398b76 100 } else {
Just4pLeisure 1:d5452e398b76 101 if (memread_long(&value, &curr_addr) != TERM_OK) {
Just4pLeisure 1:d5452e398b76 102 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 103 }
Just4pLeisure 1:d5452e398b76 104 }
Just4pLeisure 1:d5452e398b76 105
Just4pLeisure 1:d5452e398b76 106 // send memory value to host
Just4pLeisure 1:d5452e398b76 107 printf("%08X", value);
Just4pLeisure 1:d5452e398b76 108
Just4pLeisure 1:d5452e398b76 109 // add the terminating character
Just4pLeisure 1:d5452e398b76 110 if (curr_addr < *end_addr - 4) {
Just4pLeisure 1:d5452e398b76 111 pc.putc(TERM_OK);
Just4pLeisure 1:d5452e398b76 112 // light up the activity LED
Just4pLeisure 2:bf3a2b29259a 113 ACTIVITYLEDON;
Just4pLeisure 1:d5452e398b76 114 }
Just4pLeisure 1:d5452e398b76 115
Just4pLeisure 1:d5452e398b76 116 curr_addr += 4;
Just4pLeisure 1:d5452e398b76 117 }
Just4pLeisure 1:d5452e398b76 118
Just4pLeisure 1:d5452e398b76 119 return TERM_OK;
Just4pLeisure 1:d5452e398b76 120 }
Just4pLeisure 1:d5452e398b76 121
Just4pLeisure 1:d5452e398b76 122 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 123 /**
Just4pLeisure 1:d5452e398b76 124 Dumps the contents of a T5 ECU to a BIN file on the mbed 'disk'
Just4pLeisure 1:d5452e398b76 125 from [start_addr] up to, but not including, the [end_addr].
Just4pLeisure 1:d5452e398b76 126 MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 127
Just4pLeisure 1:d5452e398b76 128 @param start_addr block start address
Just4pLeisure 1:d5452e398b76 129 @param end_addr block end address
Just4pLeisure 1:d5452e398b76 130
Just4pLeisure 1:d5452e398b76 131 @return status flag
Just4pLeisure 1:d5452e398b76 132 */
Just4pLeisure 1:d5452e398b76 133
Just4pLeisure 1:d5452e398b76 134 uint8_t dump_trionic() {
Just4pLeisure 1:d5452e398b76 135
Just4pLeisure 1:d5452e398b76 136 // Configure the MC68332 register values to prepare for flashing
Just4pLeisure 1:d5452e398b76 137 printf("I am trying to discover what type of Trionic ECU I am connected to...\r\n");
Just4pLeisure 1:d5452e398b76 138 prep_t5_do();
Just4pLeisure 1:d5452e398b76 139 // Work out what type of FLASH chips we want to make a dump file for
Just4pLeisure 1:d5452e398b76 140 uint8_t make;
Just4pLeisure 1:d5452e398b76 141 uint8_t type;
Just4pLeisure 1:d5452e398b76 142 get_flash_id(&make, &type);
Just4pLeisure 1:d5452e398b76 143 // set up chip-specific functions
Just4pLeisure 1:d5452e398b76 144 bool (*reset_func)();
Just4pLeisure 1:d5452e398b76 145 uint32_t flash_size;
Just4pLeisure 1:d5452e398b76 146
Just4pLeisure 1:d5452e398b76 147 switch (type) {
Just4pLeisure 1:d5452e398b76 148 case AMD29F400B:
Just4pLeisure 1:d5452e398b76 149 case AMD29F400T:
Just4pLeisure 1:d5452e398b76 150 printf("I have found AMD29F400 type FLASH chips; I must be connected to a T7 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 151 reset_func = &reset_am29;
Just4pLeisure 1:d5452e398b76 152 flash_size = T7FLASHSIZE;
Just4pLeisure 1:d5452e398b76 153 break;
Just4pLeisure 1:d5452e398b76 154 case AMD29F010:
Just4pLeisure 1:d5452e398b76 155 printf("I have found AMD29F010 type FLASH chips; I must be connected to a repaired T5.5 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 156 reset_func = &reset_am29;
Just4pLeisure 1:d5452e398b76 157 flash_size = T55FLASHSIZE;
Just4pLeisure 1:d5452e398b76 158 break;
Just4pLeisure 1:d5452e398b76 159 case AMD28F010:
Just4pLeisure 1:d5452e398b76 160 case INTEL28F010:
Just4pLeisure 1:d5452e398b76 161 printf("I have found 28F010 type FLASH chips; I must be connected to a T5.5 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 162 reset_func = &reset_am28;
Just4pLeisure 1:d5452e398b76 163 flash_size = T55FLASHSIZE;
Just4pLeisure 1:d5452e398b76 164 break;
Just4pLeisure 1:d5452e398b76 165 case AMD28F512:
Just4pLeisure 1:d5452e398b76 166 case INTEL28F512:
Just4pLeisure 1:d5452e398b76 167 printf("I have found 28F512 type FLASH chips; I must be connected to a T5.2 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 168 reset_func = &reset_am28;
Just4pLeisure 1:d5452e398b76 169 flash_size = T52FLASHSIZE;
Just4pLeisure 1:d5452e398b76 170 break;
Just4pLeisure 1:d5452e398b76 171 default:
Just4pLeisure 1:d5452e398b76 172 // unknown flash type
Just4pLeisure 1:d5452e398b76 173 printf("I could not work out what FLASH chips or TRIONIC ECU I am connected to :-(\r\n");
Just4pLeisure 1:d5452e398b76 174 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 175 }
Just4pLeisure 1:d5452e398b76 176
Just4pLeisure 1:d5452e398b76 177 // reset the FLASH chips
Just4pLeisure 1:d5452e398b76 178 if (!reset_func()) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 179
Just4pLeisure 1:d5452e398b76 180 printf("Creating FLASH dump file...\r\n");
Just4pLeisure 1:d5452e398b76 181 FILE *fp = fopen("/local/original.bin", "w"); // Open "original.bin" on the local file system for writing
Just4pLeisure 1:d5452e398b76 182 if (!fp) {
Just4pLeisure 1:d5452e398b76 183 perror ("The following error occured");
Just4pLeisure 1:d5452e398b76 184 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 185 }
Just4pLeisure 1:d5452e398b76 186
Just4pLeisure 1:d5452e398b76 187 // dump memory contents
Just4pLeisure 1:d5452e398b76 188 uint32_t addr = 0x00;
Just4pLeisure 1:d5452e398b76 189 uint32_t long_value;
Just4pLeisure 1:d5452e398b76 190
Just4pLeisure 1:d5452e398b76 191 // setup start address to dump from
Just4pLeisure 1:d5452e398b76 192 if (memread_long_cmd(&addr) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 193
Just4pLeisure 1:d5452e398b76 194 timer.reset();
Just4pLeisure 1:d5452e398b76 195 timer.start();
Just4pLeisure 1:d5452e398b76 196
Just4pLeisure 1:d5452e398b76 197 while (addr < flash_size) {
Just4pLeisure 1:d5452e398b76 198 uint16_t byte_count = 0;
Just4pLeisure 1:d5452e398b76 199 while (byte_count < FILE_BUF_LENGTH) {
Just4pLeisure 1:d5452e398b76 200 // get long word
Just4pLeisure 1:d5452e398b76 201 if (memget_long(&long_value) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 202 addr += 4;
Just4pLeisure 1:d5452e398b76 203 // send memory value to file_buffer before saving to mbed 'disk'
Just4pLeisure 1:d5452e398b76 204 file_buffer[byte_count] = ((uint8_t)(long_value >> 24));
Just4pLeisure 1:d5452e398b76 205 file_buffer[byte_count+1] = ((uint8_t)(long_value >> 16));
Just4pLeisure 1:d5452e398b76 206 file_buffer[byte_count+2] = ((uint8_t)(long_value >> 8));
Just4pLeisure 1:d5452e398b76 207 file_buffer[byte_count+3] = ((uint8_t)long_value);
Just4pLeisure 1:d5452e398b76 208 byte_count +=4;
Just4pLeisure 2:bf3a2b29259a 209 // make the activity led twinkle
Just4pLeisure 2:bf3a2b29259a 210 ACTIVITYLEDON;
Just4pLeisure 1:d5452e398b76 211 }
Just4pLeisure 1:d5452e398b76 212 fwrite(file_buffer, 1, FILE_BUF_LENGTH, fp);
Just4pLeisure 1:d5452e398b76 213 if (ferror (fp)) {
Just4pLeisure 1:d5452e398b76 214 fclose (fp);
Just4pLeisure 1:d5452e398b76 215 printf ("Error writing to the FLASH BIN file.\r\n");
Just4pLeisure 1:d5452e398b76 216 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 217 }
Just4pLeisure 1:d5452e398b76 218 }
Just4pLeisure 1:d5452e398b76 219 // should 'clear' the BDM connection here but bdm_clear won't compile from here
Just4pLeisure 1:d5452e398b76 220 // instead do a memread (or anything really) but ignore the result because it's not needed for anything
Just4pLeisure 1:d5452e398b76 221 memread_long(&long_value, &addr);
Just4pLeisure 1:d5452e398b76 222 timer.stop();
Just4pLeisure 1:d5452e398b76 223 printf("Getting the FLASH dump took %#.1f seconds.\r\n",timer.read());
Just4pLeisure 1:d5452e398b76 224 fclose(fp);
Just4pLeisure 1:d5452e398b76 225 return TERM_OK;
Just4pLeisure 1:d5452e398b76 226 }
Just4pLeisure 1:d5452e398b76 227
Just4pLeisure 1:d5452e398b76 228 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 229 /**
Just4pLeisure 1:d5452e398b76 230 Erases the flash memory chip starting from [start_addr] up to, but not
Just4pLeisure 1:d5452e398b76 231 including [end_addr] and optionally verifies the result; MCU must be in
Just4pLeisure 1:d5452e398b76 232 background mode.
Just4pLeisure 1:d5452e398b76 233
Just4pLeisure 1:d5452e398b76 234 @param flash_type type of flash chip
Just4pLeisure 1:d5452e398b76 235 @param start_addr flash start address
Just4pLeisure 1:d5452e398b76 236 @param end_addr flash end address
Just4pLeisure 1:d5452e398b76 237
Just4pLeisure 1:d5452e398b76 238 @return status flag
Just4pLeisure 1:d5452e398b76 239 */
Just4pLeisure 1:d5452e398b76 240 uint8_t erase_flash(const char* flash_type, const uint32_t* start_addr,
Just4pLeisure 1:d5452e398b76 241 const uint32_t* end_addr) {
Just4pLeisure 1:d5452e398b76 242 // AM29Fxxx chips (retrofitted to Trionic 5.x; original to T7)
Just4pLeisure 1:d5452e398b76 243 if (strncmp(flash_type, "29f010", 6) == 0 ||
Just4pLeisure 1:d5452e398b76 244 strncmp(flash_type, "29f400", 6) == 0) {
Just4pLeisure 1:d5452e398b76 245 return erase_am29() ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 246 }
Just4pLeisure 1:d5452e398b76 247
Just4pLeisure 1:d5452e398b76 248 // AM28F010 chip (Trionic 5.x original)
Just4pLeisure 1:d5452e398b76 249 if (strncmp(flash_type, "28f010", 6) == 0) {
Just4pLeisure 1:d5452e398b76 250 return erase_am28(start_addr, end_addr) ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 251 }
Just4pLeisure 1:d5452e398b76 252
Just4pLeisure 1:d5452e398b76 253 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 254 }
Just4pLeisure 1:d5452e398b76 255
Just4pLeisure 1:d5452e398b76 256 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 257 /**
Just4pLeisure 1:d5452e398b76 258 Writes a batch of long words to the flash starting from [start_addr]. The
Just4pLeisure 1:d5452e398b76 259 operation interrupts if a break character is received. MCU must be in
Just4pLeisure 1:d5452e398b76 260 background mode.
Just4pLeisure 1:d5452e398b76 261
Just4pLeisure 1:d5452e398b76 262 @param flash_type type of flash chip
Just4pLeisure 1:d5452e398b76 263 @param start_addr block start address
Just4pLeisure 1:d5452e398b76 264
Just4pLeisure 1:d5452e398b76 265 @return status flag
Just4pLeisure 1:d5452e398b76 266 */
Just4pLeisure 1:d5452e398b76 267 uint8_t write_flash(const char* flash_type, const uint32_t* start_addr) {
Just4pLeisure 1:d5452e398b76 268 // set up chip-specific functions
Just4pLeisure 1:d5452e398b76 269 bool (*reset_func)(void);
Just4pLeisure 1:d5452e398b76 270 bool (*flash_func)(const uint32_t*, uint16_t);
Just4pLeisure 1:d5452e398b76 271
Just4pLeisure 1:d5452e398b76 272 // AM29Fxxx chips (retrofitted to Trionic 5.x, original to T7)
Just4pLeisure 1:d5452e398b76 273 if (strncmp(flash_type, "29f010", 6) == 0 ||
Just4pLeisure 1:d5452e398b76 274 strncmp(flash_type, "29f400", 6) == 0) {
Just4pLeisure 1:d5452e398b76 275 reset_func = &reset_am29;
Just4pLeisure 1:d5452e398b76 276 flash_func = &flash_am29;
Just4pLeisure 1:d5452e398b76 277 } else if (strncmp(flash_type, "28f010", 6) == 0) {
Just4pLeisure 1:d5452e398b76 278 // AM28F010 chip (Trionic 5.x original)
Just4pLeisure 1:d5452e398b76 279 reset_func = &reset_am28;
Just4pLeisure 1:d5452e398b76 280 flash_func = &flash_am28;
Just4pLeisure 1:d5452e398b76 281 } else {
Just4pLeisure 1:d5452e398b76 282 // unknown flash type
Just4pLeisure 1:d5452e398b76 283 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 284 }
Just4pLeisure 1:d5452e398b76 285
Just4pLeisure 1:d5452e398b76 286 // reset the flash
Just4pLeisure 1:d5452e398b76 287 if (!reset_func()) {
Just4pLeisure 1:d5452e398b76 288 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 289 }
Just4pLeisure 1:d5452e398b76 290
Just4pLeisure 1:d5452e398b76 291 uint32_t curr_addr = *start_addr;
Just4pLeisure 1:d5452e398b76 292 if (strncmp(flash_type, "29f010", 6) == 0) {
Just4pLeisure 1:d5452e398b76 293 curr_addr = 0;
Just4pLeisure 1:d5452e398b76 294 }
Just4pLeisure 1:d5452e398b76 295
Just4pLeisure 1:d5452e398b76 296 int rx_char = 0;
Just4pLeisure 1:d5452e398b76 297 char rx_buf[8];
Just4pLeisure 1:d5452e398b76 298 char* rx_ptr;
Just4pLeisure 1:d5452e398b76 299 uint32_t long_value;
Just4pLeisure 1:d5452e398b76 300 bool ret = true;
Just4pLeisure 1:d5452e398b76 301
Just4pLeisure 1:d5452e398b76 302 // ready to receive data
Just4pLeisure 1:d5452e398b76 303 pc.putc(TERM_OK);
Just4pLeisure 1:d5452e398b76 304
Just4pLeisure 1:d5452e398b76 305 while (true) {
Just4pLeisure 1:d5452e398b76 306 // receive long words from USB
Just4pLeisure 1:d5452e398b76 307 printf("receive long words from USB\r\n");
Just4pLeisure 1:d5452e398b76 308 rx_ptr = rx_buf;
Just4pLeisure 1:d5452e398b76 309 do {
Just4pLeisure 1:d5452e398b76 310 rx_char = pc.getc();
Just4pLeisure 1:d5452e398b76 311 if (rx_char != EOF) {
Just4pLeisure 1:d5452e398b76 312 // have got all characters for one long word
Just4pLeisure 1:d5452e398b76 313 if (rx_ptr > &rx_buf[7]) {
Just4pLeisure 1:d5452e398b76 314 ret = (rx_char == TERM_OK);
Just4pLeisure 1:d5452e398b76 315 break;
Just4pLeisure 1:d5452e398b76 316 }
Just4pLeisure 1:d5452e398b76 317
Just4pLeisure 1:d5452e398b76 318 // save the character
Just4pLeisure 1:d5452e398b76 319 *rx_ptr++ = (char)rx_char;
Just4pLeisure 1:d5452e398b76 320 }
Just4pLeisure 1:d5452e398b76 321 } while (rx_char != TERM_OK && rx_char != TERM_BREAK);
Just4pLeisure 1:d5452e398b76 322 // end writing
Just4pLeisure 1:d5452e398b76 323 printf("end writing\r\n");
Just4pLeisure 1:d5452e398b76 324 if (!ret || rx_char == TERM_BREAK) {
Just4pLeisure 1:d5452e398b76 325 break;
Just4pLeisure 1:d5452e398b76 326 }
Just4pLeisure 1:d5452e398b76 327
Just4pLeisure 1:d5452e398b76 328 // convert value to long word
Just4pLeisure 1:d5452e398b76 329 printf("convert value to long word\r\n");
Just4pLeisure 1:d5452e398b76 330 if (!ascii2int(&long_value, rx_buf, 8)) {
Just4pLeisure 1:d5452e398b76 331 ret = false;
Just4pLeisure 1:d5452e398b76 332 break;
Just4pLeisure 1:d5452e398b76 333 }
Just4pLeisure 1:d5452e398b76 334 printf("long value %08x \r\n", long_value);
Just4pLeisure 1:d5452e398b76 335
Just4pLeisure 1:d5452e398b76 336 // write the first word
Just4pLeisure 1:d5452e398b76 337 printf("write the first word\r\n");
Just4pLeisure 1:d5452e398b76 338 if (!flash_func(&curr_addr, (uint16_t)(long_value >> 16))) {
Just4pLeisure 1:d5452e398b76 339 ret = false;
Just4pLeisure 1:d5452e398b76 340 break;
Just4pLeisure 1:d5452e398b76 341 }
Just4pLeisure 1:d5452e398b76 342 curr_addr += 2;
Just4pLeisure 1:d5452e398b76 343 // write the second word
Just4pLeisure 1:d5452e398b76 344 printf("write the second word\r\n");
Just4pLeisure 1:d5452e398b76 345 if (!flash_func(&curr_addr, (uint16_t)long_value)) {
Just4pLeisure 1:d5452e398b76 346 ret = false;
Just4pLeisure 1:d5452e398b76 347 break;
Just4pLeisure 1:d5452e398b76 348 }
Just4pLeisure 1:d5452e398b76 349 curr_addr += 2;
Just4pLeisure 1:d5452e398b76 350
Just4pLeisure 1:d5452e398b76 351 // light up the activity LED
Just4pLeisure 2:bf3a2b29259a 352 ACTIVITYLEDON;
Just4pLeisure 1:d5452e398b76 353 }
Just4pLeisure 1:d5452e398b76 354
Just4pLeisure 1:d5452e398b76 355 // reset flash
Just4pLeisure 1:d5452e398b76 356 return (reset_func() && ret) ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 357 }
Just4pLeisure 1:d5452e398b76 358
Just4pLeisure 1:d5452e398b76 359 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 360 /**
Just4pLeisure 1:d5452e398b76 361 Writes a BIN file to the flash starting from [start_addr].
Just4pLeisure 1:d5452e398b76 362 The operation ends when no more bytes can be read from the BIN file.
Just4pLeisure 1:d5452e398b76 363 MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 364
Just4pLeisure 1:d5452e398b76 365 @param flash_type type of flash chip
Just4pLeisure 1:d5452e398b76 366 @param start_addr block start address
Just4pLeisure 1:d5452e398b76 367
Just4pLeisure 1:d5452e398b76 368 @return status flag
Just4pLeisure 1:d5452e398b76 369 */
Just4pLeisure 1:d5452e398b76 370 uint8_t flash_trionic() {
Just4pLeisure 1:d5452e398b76 371 // Configure the MC68332 register values to prepare for flashing
Just4pLeisure 1:d5452e398b76 372 printf("I am trying to discover what type of Trionic ECU I am connected to...\r\n");
Just4pLeisure 1:d5452e398b76 373 prep_t5_do();
Just4pLeisure 1:d5452e398b76 374 // Work out what type of FLASH chips we want to program
Just4pLeisure 1:d5452e398b76 375 uint8_t make;
Just4pLeisure 1:d5452e398b76 376 uint8_t type;
Just4pLeisure 1:d5452e398b76 377 get_flash_id(&make, &type);
Just4pLeisure 1:d5452e398b76 378 // set up chip-specific functions
Just4pLeisure 1:d5452e398b76 379 bool (*reset_func)();
Just4pLeisure 1:d5452e398b76 380 bool (*flash_func)(const uint32_t*, uint16_t);
Just4pLeisure 1:d5452e398b76 381 uint32_t flash_size;
Just4pLeisure 1:d5452e398b76 382
Just4pLeisure 1:d5452e398b76 383 switch (type) {
Just4pLeisure 1:d5452e398b76 384 case AMD29F400B:
Just4pLeisure 1:d5452e398b76 385 case AMD29F400T:
Just4pLeisure 1:d5452e398b76 386 printf("I have found AMD29F400 type FLASH chips; I must be connected to a T7 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 387 reset_func = &reset_am29;
Just4pLeisure 1:d5452e398b76 388 flash_func = &flash_am29;
Just4pLeisure 1:d5452e398b76 389 flash_size = T7FLASHSIZE;
Just4pLeisure 1:d5452e398b76 390 break;
Just4pLeisure 1:d5452e398b76 391 case AMD29F010:
Just4pLeisure 1:d5452e398b76 392 printf("I have found AMD29F010 type FLASH chips; I must be connected to a repaired T5.5 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 393 reset_func = &reset_am29;
Just4pLeisure 1:d5452e398b76 394 flash_func = &flash_am29;
Just4pLeisure 1:d5452e398b76 395 flash_size = T55FLASHSIZE;
Just4pLeisure 1:d5452e398b76 396 break;
Just4pLeisure 1:d5452e398b76 397 case AMD28F010:
Just4pLeisure 1:d5452e398b76 398 case INTEL28F010:
Just4pLeisure 1:d5452e398b76 399 printf("I have found 28F010 type FLASH chips; I must be connected to a T5.5 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 400 reset_func = &reset_am28;
Just4pLeisure 1:d5452e398b76 401 flash_func = &flash_am28;
Just4pLeisure 1:d5452e398b76 402 flash_size = T55FLASHSIZE;
Just4pLeisure 1:d5452e398b76 403 break;
Just4pLeisure 1:d5452e398b76 404 case AMD28F512:
Just4pLeisure 1:d5452e398b76 405 case INTEL28F512:
Just4pLeisure 1:d5452e398b76 406 printf("I have found 28F512 type FLASH chips; I must be connected to a T5.2 ECU :-)\r\n");
Just4pLeisure 1:d5452e398b76 407 reset_func = &reset_am28;
Just4pLeisure 1:d5452e398b76 408 flash_func = &flash_am28;
Just4pLeisure 1:d5452e398b76 409 flash_size = T52FLASHSIZE;
Just4pLeisure 1:d5452e398b76 410 break;
Just4pLeisure 1:d5452e398b76 411 default:
Just4pLeisure 1:d5452e398b76 412 // unknown flash type
Just4pLeisure 1:d5452e398b76 413 printf("I could not work out what FLASH chips or TRIONIC ECU I am connected to :-(\r\n");
Just4pLeisure 1:d5452e398b76 414 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 415 }
Just4pLeisure 1:d5452e398b76 416
Just4pLeisure 1:d5452e398b76 417 // reset the FLASH chips
Just4pLeisure 1:d5452e398b76 418 if (!reset_func()) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 419
Just4pLeisure 1:d5452e398b76 420 printf("Checking the FLASH BIN file...\r\n");
Just4pLeisure 1:d5452e398b76 421 FILE *fp = fopen("/local/modified.hex", "r"); // Open "modified.hex" on the local file system for reading
Just4pLeisure 1:d5452e398b76 422 if (!fp) {
Just4pLeisure 1:d5452e398b76 423 printf("Error: I could not find the BIN file MODIFIED.HEX\r\n");;
Just4pLeisure 1:d5452e398b76 424 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 425 }
Just4pLeisure 1:d5452e398b76 426 // obtain file size - it should match the size of the FLASH chips:
Just4pLeisure 1:d5452e398b76 427 fseek (fp , 0 , SEEK_END);
Just4pLeisure 1:d5452e398b76 428 uint32_t file_size = ftell (fp);
Just4pLeisure 1:d5452e398b76 429 rewind (fp);
Just4pLeisure 1:d5452e398b76 430
Just4pLeisure 1:d5452e398b76 431 // read the initial stack pointer value in the BIN file - it should match the value expected for the type of ECU
Just4pLeisure 1:d5452e398b76 432 uint8_t stack_byte = 0;
Just4pLeisure 1:d5452e398b76 433 uint32_t stack_long = 0;
Just4pLeisure 1:d5452e398b76 434 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 435 stack_long |= (stack_byte << 24);
Just4pLeisure 1:d5452e398b76 436 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 437 stack_long |= (stack_byte << 16);
Just4pLeisure 1:d5452e398b76 438 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 439 stack_long |= (stack_byte << 8);
Just4pLeisure 1:d5452e398b76 440 if (!fread(&stack_byte,1,1,fp)) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 441 stack_long |= stack_byte;
Just4pLeisure 1:d5452e398b76 442 rewind (fp);
Just4pLeisure 1:d5452e398b76 443
Just4pLeisure 1:d5452e398b76 444 if (flash_size == T52FLASHSIZE && (file_size != T52FLASHSIZE || stack_long != T5POINTER)) {
Just4pLeisure 1:d5452e398b76 445 fclose(fp);
Just4pLeisure 1:d5452e398b76 446 printf("The BIN file does not appear to be for a T5.2 ECU :-(\r\n");
Just4pLeisure 1:d5452e398b76 447 printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, flash_size, stack_long);
Just4pLeisure 1:d5452e398b76 448 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 449 }
Just4pLeisure 1:d5452e398b76 450 if (flash_size == T55FLASHSIZE && (file_size != T55FLASHSIZE || stack_long != T5POINTER)) {
Just4pLeisure 1:d5452e398b76 451 fclose(fp);
Just4pLeisure 1:d5452e398b76 452 printf("The BIN file does not appear to be for a T5.5 ECU :-(\r\n");
Just4pLeisure 1:d5452e398b76 453 printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, flash_size, stack_long);
Just4pLeisure 1:d5452e398b76 454 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 455 }
Just4pLeisure 1:d5452e398b76 456 if (flash_size == T7FLASHSIZE && (file_size != T7FLASHSIZE || stack_long != T7POINTER)) {
Just4pLeisure 1:d5452e398b76 457 fclose(fp);
Just4pLeisure 1:d5452e398b76 458 printf("The BIN file does not appear to be for a T7 ECU :-(\r\n");
Just4pLeisure 1:d5452e398b76 459 printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, flash_size, stack_long);
Just4pLeisure 1:d5452e398b76 460 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 461 }
Just4pLeisure 1:d5452e398b76 462
Just4pLeisure 1:d5452e398b76 463 timer.reset();
Just4pLeisure 1:d5452e398b76 464 timer.start();
Just4pLeisure 1:d5452e398b76 465
Just4pLeisure 1:d5452e398b76 466 uint32_t curr_addr = 0;
Just4pLeisure 1:d5452e398b76 467
Just4pLeisure 1:d5452e398b76 468 switch (type) {
Just4pLeisure 1:d5452e398b76 469 // AM29Fxxx chips (retrofitted to Trionic 5.x; original to T7)
Just4pLeisure 1:d5452e398b76 470 case AMD29F400B:
Just4pLeisure 1:d5452e398b76 471 case AMD29F400T:
Just4pLeisure 1:d5452e398b76 472 case AMD29F010:
Just4pLeisure 1:d5452e398b76 473 printf("Erasing 29F400/010 type FLASH chips...\r\n");
Just4pLeisure 2:bf3a2b29259a 474 if (!erase_am29()) {
Just4pLeisure 1:d5452e398b76 475 printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n");
Just4pLeisure 1:d5452e398b76 476 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 477 }
Just4pLeisure 1:d5452e398b76 478 break;
Just4pLeisure 1:d5452e398b76 479 // AM28F010 chip (Trionic 5.x original)
Just4pLeisure 1:d5452e398b76 480 case AMD28F010:
Just4pLeisure 1:d5452e398b76 481 case INTEL28F010:
Just4pLeisure 1:d5452e398b76 482 case AMD28F512:
Just4pLeisure 1:d5452e398b76 483 case INTEL28F512:
Just4pLeisure 1:d5452e398b76 484 printf("Erasing 28F010/512 type FLASH chips...\r\n");
Just4pLeisure 2:bf3a2b29259a 485 if (!erase_am28(&curr_addr, &flash_size)) {
Just4pLeisure 1:d5452e398b76 486 printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n");
Just4pLeisure 1:d5452e398b76 487 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 488 }
Just4pLeisure 1:d5452e398b76 489 break;
Just4pLeisure 1:d5452e398b76 490 default:
Just4pLeisure 1:d5452e398b76 491 // unknown flash type - shouldn't get here hence "Starange!"
Just4pLeisure 1:d5452e398b76 492 printf("Strange! I couldn't work out how to erase the FLASH chips in the TRIONIC ECU that I am connected to :-(\r\n");
Just4pLeisure 1:d5452e398b76 493 return TERM_ERR;
Just4pLeisure 1:d5452e398b76 494 }
Just4pLeisure 1:d5452e398b76 495
Just4pLeisure 1:d5452e398b76 496 timer.stop();
Just4pLeisure 1:d5452e398b76 497 printf("Erasing took %#.1f seconds.\r\n",timer.read());
Just4pLeisure 1:d5452e398b76 498
Just4pLeisure 1:d5452e398b76 499 printf("Programming the FLASH chips...\r\n");
Just4pLeisure 1:d5452e398b76 500
Just4pLeisure 1:d5452e398b76 501 timer.reset();
Just4pLeisure 1:d5452e398b76 502 timer.start();
Just4pLeisure 1:d5452e398b76 503
Just4pLeisure 1:d5452e398b76 504 uint16_t word_value = 0;
Just4pLeisure 1:d5452e398b76 505 uint8_t byte_value = 0;
Just4pLeisure 1:d5452e398b76 506 // bool ret = true;
Just4pLeisure 1:d5452e398b76 507
Just4pLeisure 1:d5452e398b76 508 // ready to receive data
Just4pLeisure 1:d5452e398b76 509 while (curr_addr < flash_size) {
Just4pLeisure 1:d5452e398b76 510 // receive bytes from BIN file
Just4pLeisure 1:d5452e398b76 511 //Get a byte - break if no more bytes to get
Just4pLeisure 1:d5452e398b76 512 if (!fread(&byte_value,1,1,fp)) {
Just4pLeisure 1:d5452e398b76 513 fclose(fp);
Just4pLeisure 1:d5452e398b76 514 printf("Error reading the BIN file MODIFIED.HEX");
Just4pLeisure 1:d5452e398b76 515 break;
Just4pLeisure 1:d5452e398b76 516 }
Just4pLeisure 1:d5452e398b76 517 word_value = (byte_value << 8);
Just4pLeisure 1:d5452e398b76 518 if (!fread(&byte_value,1,1,fp)) {
Just4pLeisure 1:d5452e398b76 519 fclose(fp);
Just4pLeisure 1:d5452e398b76 520 printf("Error reading the BIN file MODIFIED.HEX");
Just4pLeisure 1:d5452e398b76 521 break;
Just4pLeisure 1:d5452e398b76 522 }
Just4pLeisure 1:d5452e398b76 523 word_value |= byte_value;
Just4pLeisure 1:d5452e398b76 524
Just4pLeisure 1:d5452e398b76 525 // write the word if it is not 0xffff
Just4pLeisure 1:d5452e398b76 526 if (word_value != 0xffff) {
Just4pLeisure 1:d5452e398b76 527 if (!flash_func(&curr_addr, word_value)) break;
Just4pLeisure 1:d5452e398b76 528 }
Just4pLeisure 1:d5452e398b76 529 curr_addr += 2;
Just4pLeisure 1:d5452e398b76 530
Just4pLeisure 1:d5452e398b76 531 // make the activity LED twinkle
Just4pLeisure 2:bf3a2b29259a 532 ACTIVITYLEDON;
Just4pLeisure 1:d5452e398b76 533 }
Just4pLeisure 1:d5452e398b76 534
Just4pLeisure 1:d5452e398b76 535 timer.stop();
Just4pLeisure 1:d5452e398b76 536 fclose(fp);
Just4pLeisure 1:d5452e398b76 537
Just4pLeisure 1:d5452e398b76 538 if (curr_addr == flash_size) {
Just4pLeisure 1:d5452e398b76 539 printf("Programming took %#.1f seconds.\r\n",timer.read());
Just4pLeisure 1:d5452e398b76 540 reset_func();
Just4pLeisure 1:d5452e398b76 541 for (uint8_t i = 0; i < 8; ++i) {
Just4pLeisure 1:d5452e398b76 542 memread_word(&word_value, &flash_tag[i].addr);
Just4pLeisure 1:d5452e398b76 543 flash_func(&flash_tag[i].addr, (flash_tag[i].val & word_value));
Just4pLeisure 1:d5452e398b76 544 }
Just4pLeisure 1:d5452e398b76 545
Just4pLeisure 1:d5452e398b76 546 } else {
Just4pLeisure 1:d5452e398b76 547 printf("WARNING: Oh dear, I couldn't program the FLASH at address 0x%8x.\r\n", curr_addr);
Just4pLeisure 1:d5452e398b76 548 }
Just4pLeisure 1:d5452e398b76 549
Just4pLeisure 1:d5452e398b76 550 // reset flash
Just4pLeisure 1:d5452e398b76 551 return (reset_func() && (curr_addr == flash_size)) ? TERM_OK : TERM_ERR;
Just4pLeisure 1:d5452e398b76 552 }
Just4pLeisure 1:d5452e398b76 553
Just4pLeisure 1:d5452e398b76 554 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 555 /**
Just4pLeisure 1:d5452e398b76 556 Resets an AM29Fxxx flash memory chip. MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 557
Just4pLeisure 1:d5452e398b76 558 @param none
Just4pLeisure 1:d5452e398b76 559
Just4pLeisure 1:d5452e398b76 560 @return succ / fail
Just4pLeisure 1:d5452e398b76 561 */
Just4pLeisure 1:d5452e398b76 562 bool reset_am29(void) {
Just4pLeisure 1:d5452e398b76 563 // execute the reset command
Just4pLeisure 1:d5452e398b76 564 // uint32_t addr = 0xfffe;
Just4pLeisure 1:d5452e398b76 565 // return (memwrite_word(&addr, 0xf0f0) == TERM_OK);
Just4pLeisure 1:d5452e398b76 566 // execute the algorithm
Just4pLeisure 1:d5452e398b76 567 for (uint8_t i = 0; i < 3; ++i) {
Just4pLeisure 1:d5452e398b76 568 if (memwrite_word(&am29_reset[i].addr, am29_reset[i].val) != TERM_OK) return false;
Just4pLeisure 1:d5452e398b76 569 }
Just4pLeisure 1:d5452e398b76 570 return true;
Just4pLeisure 1:d5452e398b76 571 }
Just4pLeisure 1:d5452e398b76 572
Just4pLeisure 1:d5452e398b76 573 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 574 /**
Just4pLeisure 1:d5452e398b76 575 Erases an AM29Fxxx flash memory chip and verifies the result; MCU must be
Just4pLeisure 1:d5452e398b76 576 in background mode.
Just4pLeisure 1:d5452e398b76 577
Just4pLeisure 1:d5452e398b76 578 @return succ / fail
Just4pLeisure 1:d5452e398b76 579 */
Just4pLeisure 1:d5452e398b76 580 bool erase_am29() {
Just4pLeisure 1:d5452e398b76 581 // reset flash
Just4pLeisure 1:d5452e398b76 582 if (!reset_am29()) {
Just4pLeisure 1:d5452e398b76 583 return false;
Just4pLeisure 1:d5452e398b76 584 }
Just4pLeisure 1:d5452e398b76 585
Just4pLeisure 1:d5452e398b76 586 // execute the algorithm
Just4pLeisure 1:d5452e398b76 587 for (uint8_t i = 0; i < 6; ++i) {
Just4pLeisure 1:d5452e398b76 588 if (memwrite_word(&am29_erase[i].addr, am29_erase[i].val) != TERM_OK) {
Just4pLeisure 1:d5452e398b76 589 reset_am29();
Just4pLeisure 1:d5452e398b76 590 return false;
Just4pLeisure 1:d5452e398b76 591 }
Just4pLeisure 1:d5452e398b76 592 }
Just4pLeisure 1:d5452e398b76 593
Just4pLeisure 1:d5452e398b76 594 // verify the result
Just4pLeisure 1:d5452e398b76 595 uint32_t addr = 0x0;
Just4pLeisure 1:d5452e398b76 596 uint16_t verify_value;
Just4pLeisure 1:d5452e398b76 597
Just4pLeisure 1:d5452e398b76 598 uint8_t err_cnt = ERR_COUNT;
Just4pLeisure 1:d5452e398b76 599 while (--err_cnt) {
Just4pLeisure 1:d5452e398b76 600 // typical erase time = 1s
Just4pLeisure 1:d5452e398b76 601 // Allow up to 25.5 seconds erase time
Just4pLeisure 1:d5452e398b76 602 wait_ms(100);
Just4pLeisure 1:d5452e398b76 603 if (memread_word(&verify_value, &addr) == TERM_OK && verify_value == 0xffff) {
Just4pLeisure 1:d5452e398b76 604 // erase completed normally
Just4pLeisure 1:d5452e398b76 605 reset_am29();
Just4pLeisure 1:d5452e398b76 606 return true;
Just4pLeisure 1:d5452e398b76 607 }
Just4pLeisure 1:d5452e398b76 608 }
Just4pLeisure 1:d5452e398b76 609
Just4pLeisure 1:d5452e398b76 610 // erase failed
Just4pLeisure 1:d5452e398b76 611 reset_am29();
Just4pLeisure 1:d5452e398b76 612 return false;
Just4pLeisure 1:d5452e398b76 613 }
Just4pLeisure 1:d5452e398b76 614
Just4pLeisure 1:d5452e398b76 615 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 616 /**
Just4pLeisure 1:d5452e398b76 617 Writes a word to AM29Fxxx flash memory chip and optionally verifies the
Just4pLeisure 1:d5452e398b76 618 result; MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 619
Just4pLeisure 1:d5452e398b76 620 @param addr destination address
Just4pLeisure 1:d5452e398b76 621 @param val value
Just4pLeisure 1:d5452e398b76 622
Just4pLeisure 1:d5452e398b76 623 @return succ / fail
Just4pLeisure 1:d5452e398b76 624 */
Just4pLeisure 1:d5452e398b76 625 bool flash_am29(const uint32_t* addr, uint16_t value) {
Just4pLeisure 1:d5452e398b76 626
Just4pLeisure 1:d5452e398b76 627 // execute the algorithm
Just4pLeisure 1:d5452e398b76 628 for (uint8_t i = 0; i < 3; ++i) {
Just4pLeisure 1:d5452e398b76 629 if (memwrite_word(&am29_write[i].addr, am29_write[i].val) != TERM_OK) {
Just4pLeisure 1:d5452e398b76 630 reset_am29();
Just4pLeisure 1:d5452e398b76 631 return false;
Just4pLeisure 1:d5452e398b76 632 }
Just4pLeisure 1:d5452e398b76 633 }
Just4pLeisure 1:d5452e398b76 634 // write the value
Just4pLeisure 1:d5452e398b76 635 if (memwrite_word(addr, value) != TERM_OK) {
Just4pLeisure 1:d5452e398b76 636 reset_am29();
Just4pLeisure 1:d5452e398b76 637 return false;
Just4pLeisure 1:d5452e398b76 638 }
Just4pLeisure 1:d5452e398b76 639 // verify the result
Just4pLeisure 1:d5452e398b76 640 uint8_t err_cnt = ERR_COUNT;
Just4pLeisure 1:d5452e398b76 641 while (--err_cnt) {
Just4pLeisure 1:d5452e398b76 642 // Allow up to approx 2.55 milliseconds program time (255 * ~10us BDM memread time)
Just4pLeisure 1:d5452e398b76 643 // wait_ms(10);
Just4pLeisure 1:d5452e398b76 644 uint16_t verify_value;
Just4pLeisure 1:d5452e398b76 645 if ((memread_word(&verify_value, addr) == TERM_OK) &&
Just4pLeisure 1:d5452e398b76 646 (verify_value == value)) {
Just4pLeisure 1:d5452e398b76 647 // flashing successful
Just4pLeisure 1:d5452e398b76 648 return true;
Just4pLeisure 1:d5452e398b76 649 }
Just4pLeisure 1:d5452e398b76 650 }
Just4pLeisure 1:d5452e398b76 651 // writing failed
Just4pLeisure 1:d5452e398b76 652 reset_am29();
Just4pLeisure 1:d5452e398b76 653 return false;
Just4pLeisure 1:d5452e398b76 654 }
Just4pLeisure 1:d5452e398b76 655
Just4pLeisure 1:d5452e398b76 656 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 657 /**
Just4pLeisure 1:d5452e398b76 658 Resets a AM28Fxxx flash memory chip. MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 659
Just4pLeisure 1:d5452e398b76 660 @param start_addr flash start address
Just4pLeisure 1:d5452e398b76 661
Just4pLeisure 1:d5452e398b76 662 @return succ / fail
Just4pLeisure 1:d5452e398b76 663 */
Just4pLeisure 1:d5452e398b76 664 bool reset_am28(void) {
Just4pLeisure 1:d5452e398b76 665 uint32_t start_addr = 0x0;
Just4pLeisure 2:bf3a2b29259a 666 return (memwrite_word_write_word(&start_addr, 0xffff, 0xffff) == TERM_OK);
Just4pLeisure 1:d5452e398b76 667 }
Just4pLeisure 1:d5452e398b76 668
Just4pLeisure 1:d5452e398b76 669 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 670 /**
Just4pLeisure 1:d5452e398b76 671 Erases an AM28Fxxx flash memory chip and verifies the result; MCU must be
Just4pLeisure 1:d5452e398b76 672 in background mode.
Just4pLeisure 1:d5452e398b76 673
Just4pLeisure 1:d5452e398b76 674 @param start_addr flash start address
Just4pLeisure 1:d5452e398b76 675 @param end_addr flash end address
Just4pLeisure 1:d5452e398b76 676
Just4pLeisure 1:d5452e398b76 677 @return succ / fail
Just4pLeisure 1:d5452e398b76 678 */
Just4pLeisure 1:d5452e398b76 679 bool erase_am28(const uint32_t* start_addr, const uint32_t* end_addr) {
Just4pLeisure 1:d5452e398b76 680
Just4pLeisure 1:d5452e398b76 681 // check the addresses
Just4pLeisure 1:d5452e398b76 682 if (!start_addr || !end_addr) return false;
Just4pLeisure 1:d5452e398b76 683
Just4pLeisure 1:d5452e398b76 684 // reset flash
Just4pLeisure 1:d5452e398b76 685 if (!reset_am28()) return false;
Just4pLeisure 1:d5452e398b76 686
Just4pLeisure 1:d5452e398b76 687 // write zeroes over entire flash space
Just4pLeisure 1:d5452e398b76 688 uint32_t addr = *start_addr;
Just4pLeisure 1:d5452e398b76 689
Just4pLeisure 1:d5452e398b76 690 while (addr < *end_addr) {
Just4pLeisure 1:d5452e398b76 691 if (!flash_am28(&addr, 0x0000)) return false;
Just4pLeisure 1:d5452e398b76 692 addr += 2;
Just4pLeisure 1:d5452e398b76 693 // // feedback to host computer
Just4pLeisure 1:d5452e398b76 694 // pc.putc(TERM_OK);
Just4pLeisure 1:d5452e398b76 695 // make the activity LED twinkle
Just4pLeisure 2:bf3a2b29259a 696 ACTIVITYLEDON;
Just4pLeisure 2:bf3a2b29259a 697
Just4pLeisure 1:d5452e398b76 698 }
Just4pLeisure 1:d5452e398b76 699
Just4pLeisure 1:d5452e398b76 700 // erase flash
Just4pLeisure 1:d5452e398b76 701 addr = *start_addr;
Just4pLeisure 1:d5452e398b76 702 uint8_t verify_value;
Just4pLeisure 1:d5452e398b76 703
Just4pLeisure 1:d5452e398b76 704 uint16_t pulse_cnt = 0;
Just4pLeisure 1:d5452e398b76 705 if (memwrite_byte_cmd(NULL) != TERM_OK) {
Just4pLeisure 1:d5452e398b76 706 reset_am28();
Just4pLeisure 1:d5452e398b76 707 return false;
Just4pLeisure 1:d5452e398b76 708 }
Just4pLeisure 1:d5452e398b76 709 while ((++pulse_cnt < 1000) && (addr < *end_addr)) {
Just4pLeisure 1:d5452e398b76 710 // issue the erase command
Just4pLeisure 1:d5452e398b76 711 if (memwrite_write_byte(&addr, 0x20) != TERM_OK ||
Just4pLeisure 1:d5452e398b76 712 memwrite_write_byte(&addr, 0x20) != TERM_OK) break;
Just4pLeisure 1:d5452e398b76 713 wait_ms(10);
Just4pLeisure 1:d5452e398b76 714
Just4pLeisure 1:d5452e398b76 715 while (addr < *end_addr) {
Just4pLeisure 1:d5452e398b76 716 // issue the verify command
Just4pLeisure 1:d5452e398b76 717 if (memwrite_read_byte(&addr, 0xa0) != TERM_OK) break;
Just4pLeisure 1:d5452e398b76 718 // wait_us(6);
Just4pLeisure 1:d5452e398b76 719 // check the written value
Just4pLeisure 1:d5452e398b76 720 if (memread_write_byte(&verify_value, &addr) != TERM_OK) break;
Just4pLeisure 1:d5452e398b76 721 if (verify_value != 0xff) break;
Just4pLeisure 1:d5452e398b76 722 // succeeded need to check next address
Just4pLeisure 1:d5452e398b76 723 addr++;
Just4pLeisure 1:d5452e398b76 724 // make the activity LED twinkle
Just4pLeisure 2:bf3a2b29259a 725 ACTIVITYLEDON;
Just4pLeisure 1:d5452e398b76 726 }
Just4pLeisure 1:d5452e398b76 727 }
Just4pLeisure 1:d5452e398b76 728 // the erase process ends with a BDM_WRITE + BDM_BYTESIZE command left in the BDM
Just4pLeisure 1:d5452e398b76 729 // it is safe to use it to put one of the FLASH chips into read mode and thereby
Just4pLeisure 1:d5452e398b76 730 // leave the BDM ready for the next command
Just4pLeisure 1:d5452e398b76 731 memwrite_nop_byte(start_addr, 0x00);
Just4pLeisure 1:d5452e398b76 732
Just4pLeisure 1:d5452e398b76 733 reset_am28();
Just4pLeisure 1:d5452e398b76 734 // check for success
Just4pLeisure 1:d5452e398b76 735 return (addr == *end_addr) ? true : false;
Just4pLeisure 1:d5452e398b76 736 }
Just4pLeisure 1:d5452e398b76 737
Just4pLeisure 1:d5452e398b76 738 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 739 /**
Just4pLeisure 1:d5452e398b76 740 Writes a byte to AM28Fxxx flash memory chip and verifies the result
Just4pLeisure 1:d5452e398b76 741 A so called 'mask' method checks the FLASH contents and only tries
Just4pLeisure 1:d5452e398b76 742 to program bytes that need to be programmed.
Just4pLeisure 1:d5452e398b76 743 MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 744
Just4pLeisure 1:d5452e398b76 745 @param addr destination address
Just4pLeisure 1:d5452e398b76 746 @param val value
Just4pLeisure 1:d5452e398b76 747
Just4pLeisure 1:d5452e398b76 748 @return succ / fail
Just4pLeisure 1:d5452e398b76 749 */
Just4pLeisure 1:d5452e398b76 750 bool flash_am28(const uint32_t* addr, uint16_t value) {
Just4pLeisure 1:d5452e398b76 751
Just4pLeisure 1:d5452e398b76 752 if (!addr) return false;
Just4pLeisure 1:d5452e398b76 753
Just4pLeisure 1:d5452e398b76 754 uint8_t pulse_cnt = 0;
Just4pLeisure 1:d5452e398b76 755 uint16_t verify_value = 0;
Just4pLeisure 1:d5452e398b76 756 uint16_t mask_value = 0xffff;
Just4pLeisure 1:d5452e398b76 757
Just4pLeisure 1:d5452e398b76 758 // put flash into read mode and read address
Just4pLeisure 1:d5452e398b76 759 if (memwrite_word_read_word(&verify_value, addr, 0x0000) != TERM_OK) return false;
Just4pLeisure 1:d5452e398b76 760 // return if FLASH already has the correct value - e.g. not all of the FLASH is used and is 0xff
Just4pLeisure 1:d5452e398b76 761 if (verify_value == value) return true;
Just4pLeisure 1:d5452e398b76 762
Just4pLeisure 1:d5452e398b76 763 while (++pulse_cnt < 25) {
Just4pLeisure 1:d5452e398b76 764
Just4pLeisure 1:d5452e398b76 765 // set a mask
Just4pLeisure 2:bf3a2b29259a 766 if ((uint8_t)verify_value == (uint8_t)value)
Just4pLeisure 2:bf3a2b29259a 767 mask_value &= 0xff00;
Just4pLeisure 2:bf3a2b29259a 768 if ((uint8_t)(verify_value >> 8) == (uint8_t)(value >> 8))
Just4pLeisure 2:bf3a2b29259a 769 mask_value &= 0x00ff;
Just4pLeisure 1:d5452e398b76 770
Just4pLeisure 1:d5452e398b76 771 // write the new value
Just4pLeisure 1:d5452e398b76 772 if (memwrite_word_write_word(addr, (0x4040 & mask_value), value) != TERM_OK) break;
Just4pLeisure 1:d5452e398b76 773 // NOTE the BDM interface is slow enough that there is no need for a 10us delay before verifying
Just4pLeisure 1:d5452e398b76 774 // issue the verification command
Just4pLeisure 1:d5452e398b76 775 // NOTE the BDM interface is slow enough that there is no need for a 6us delay before reading back
Just4pLeisure 1:d5452e398b76 776 if (memwrite_word_read_word(&verify_value, addr, (0xc0c0 & mask_value)) != TERM_OK) break;
Just4pLeisure 1:d5452e398b76 777 // check if flashing was successful;
Just4pLeisure 1:d5452e398b76 778 if (verify_value == value) return true;
Just4pLeisure 1:d5452e398b76 779 }
Just4pLeisure 1:d5452e398b76 780
Just4pLeisure 1:d5452e398b76 781 // something went wrong; reset the flash chip and return failed
Just4pLeisure 1:d5452e398b76 782 reset_am28();
Just4pLeisure 1:d5452e398b76 783 return false;
Just4pLeisure 1:d5452e398b76 784 }
Just4pLeisure 1:d5452e398b76 785
Just4pLeisure 1:d5452e398b76 786 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 787 /**
Just4pLeisure 1:d5452e398b76 788 Does the equivalent of do prept5.do in BD32
Just4pLeisure 1:d5452e398b76 789 Sets up all of the control registers in the MC68332 so that we can program
Just4pLeisure 1:d5452e398b76 790 the FLASH chips
Just4pLeisure 1:d5452e398b76 791
Just4pLeisure 1:d5452e398b76 792 @param none
Just4pLeisure 1:d5452e398b76 793
Just4pLeisure 1:d5452e398b76 794 @return succ / fail
Just4pLeisure 1:d5452e398b76 795 */
Just4pLeisure 1:d5452e398b76 796
Just4pLeisure 1:d5452e398b76 797 uint8_t prep_t5_do(void) {
Just4pLeisure 1:d5452e398b76 798
Just4pLeisure 1:d5452e398b76 799 // reset and freeze the MC68332 chip
Just4pLeisure 1:d5452e398b76 800 if (restart_chip() != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 801
Just4pLeisure 1:d5452e398b76 802 // set the 'fc' registers to allow supervisor mode access
Just4pLeisure 1:d5452e398b76 803 uint32_t long_value = 0x05;
Just4pLeisure 1:d5452e398b76 804 if (sysreg_write(0x0e, &long_value) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 805 if (sysreg_write(0x0f, &long_value) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 806
Just4pLeisure 1:d5452e398b76 807 // Set MC68332 to 16 MHz (actually 16.78 MHz)
Just4pLeisure 1:d5452e398b76 808 long_value = 0x00fffa04;
Just4pLeisure 1:d5452e398b76 809 if (memwrite_word(&long_value, 0x7f00) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 810
Just4pLeisure 1:d5452e398b76 811 // Disable watchdog and monitors
Just4pLeisure 1:d5452e398b76 812 long_value = 0x00fffa21;
Just4pLeisure 1:d5452e398b76 813 if (memwrite_byte(&long_value, 0x00) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 814
Just4pLeisure 1:d5452e398b76 815 // Chip select pin assignments
Just4pLeisure 1:d5452e398b76 816 long_value = 0x00fffa44;
Just4pLeisure 1:d5452e398b76 817 if (memwrite_word(&long_value, 0x3fff) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 818
Just4pLeisure 1:d5452e398b76 819 // Boot Chip select read only, one wait state
Just4pLeisure 1:d5452e398b76 820 long_value = 0x00fffa48;
Just4pLeisure 1:d5452e398b76 821 if (memwrite_word(&long_value, 0x0007) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 822 if (memfill_word(0x6870) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 823
Just4pLeisure 1:d5452e398b76 824 // Chip select 1 and 2 upper lower bytes, zero wait states
Just4pLeisure 1:d5452e398b76 825 long_value = 0x00fffa50;
Just4pLeisure 1:d5452e398b76 826 if (memwrite_word(&long_value, 0x0007) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 827 if (memfill_word(0x3030) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 828 if (memfill_word(0x0007) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 829 if (memfill_word(0x5030) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 830
Just4pLeisure 1:d5452e398b76 831 // PQS Data - turn on VPPH
Just4pLeisure 1:d5452e398b76 832 long_value = 0x00fffc14;
Just4pLeisure 1:d5452e398b76 833 if (memwrite_word(&long_value, 0x0040) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 834
Just4pLeisure 1:d5452e398b76 835 // PQS Data Direction output
Just4pLeisure 1:d5452e398b76 836 long_value = 0x00fffc17;
Just4pLeisure 1:d5452e398b76 837 if (memwrite_byte(&long_value, 0x40) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 838 // wait for programming voltage to be ready
Just4pLeisure 1:d5452e398b76 839 wait_ms(10);
Just4pLeisure 1:d5452e398b76 840
Just4pLeisure 1:d5452e398b76 841 // // Enable internal 2kByte RAM of 68332 at address 0x00100000
Just4pLeisure 1:d5452e398b76 842 // long_value = 0x00fffb04;
Just4pLeisure 1:d5452e398b76 843 // if (memwrite_word(&long_value, 0x1000) != TERM_OK) return TERM_ERR;
Just4pLeisure 1:d5452e398b76 844 return TERM_OK;
Just4pLeisure 1:d5452e398b76 845 }
Just4pLeisure 1:d5452e398b76 846
Just4pLeisure 1:d5452e398b76 847 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 848 /**
Just4pLeisure 1:d5452e398b76 849 Works out what type of flash chip is fitted in the ECU by reading
Just4pLeisure 1:d5452e398b76 850 the manufacturer byte codes.
Just4pLeisure 1:d5452e398b76 851 It is enough to use the 29Fxxx flash id algorithm because 28Fxxx
Just4pLeisure 1:d5452e398b76 852 FLASH chips ignore the first few writes needed by the 29Fxxx chips
Just4pLeisure 1:d5452e398b76 853 MCU must be in background mode.
Just4pLeisure 1:d5452e398b76 854
Just4pLeisure 1:d5452e398b76 855 @param make (out)
Just4pLeisure 1:d5452e398b76 856 type (out)
Just4pLeisure 1:d5452e398b76 857
Just4pLeisure 1:d5452e398b76 858 @return succ / fail
Just4pLeisure 1:d5452e398b76 859 */
Just4pLeisure 1:d5452e398b76 860 bool get_flash_id(uint8_t* make, uint8_t* type) {
Just4pLeisure 1:d5452e398b76 861
Just4pLeisure 1:d5452e398b76 862 uint32_t addr = 0x0;
Just4pLeisure 1:d5452e398b76 863 uint32_t value;
Just4pLeisure 1:d5452e398b76 864 bool ret;
Just4pLeisure 1:d5452e398b76 865 // read id bytes algorithm for 29F010/400 FLASH chips
Just4pLeisure 1:d5452e398b76 866 for (uint8_t i = 0; i < 3; ++i) {
Just4pLeisure 1:d5452e398b76 867 if (memwrite_word(&am29_id[i].addr, am29_id[i].val) != TERM_OK) return false;
Just4pLeisure 1:d5452e398b76 868 }
Just4pLeisure 1:d5452e398b76 869 if (memread_long(&value, &addr) != TERM_OK) return false;
Just4pLeisure 2:bf3a2b29259a 870 // *make = (uint8_t)(value >> 24);
Just4pLeisure 2:bf3a2b29259a 871 // *type = (uint8_t)(value >> 8);
Just4pLeisure 2:bf3a2b29259a 872 *make = (uint8_t)(value >> 16);
Just4pLeisure 2:bf3a2b29259a 873 *type = (uint8_t)(value);
Just4pLeisure 1:d5452e398b76 874 printf("FLASH id bytes: %08x, make: %02x, type: %02x\r\n", value, *make, *type);
Just4pLeisure 1:d5452e398b76 875 switch (*type) {
Just4pLeisure 1:d5452e398b76 876 case AMD29F400B:
Just4pLeisure 1:d5452e398b76 877 case AMD29F400T:
Just4pLeisure 1:d5452e398b76 878 case AMD29F010:
Just4pLeisure 1:d5452e398b76 879 case AMD28F010:
Just4pLeisure 1:d5452e398b76 880 case INTEL28F010:
Just4pLeisure 1:d5452e398b76 881 case AMD28F512:
Just4pLeisure 1:d5452e398b76 882 case INTEL28F512:
Just4pLeisure 1:d5452e398b76 883 ret = true;
Just4pLeisure 1:d5452e398b76 884 default:
Just4pLeisure 1:d5452e398b76 885 ret = false;
Just4pLeisure 1:d5452e398b76 886 }
Just4pLeisure 1:d5452e398b76 887 return ret;
Just4pLeisure 1:d5452e398b76 888 }
Just4pLeisure 1:d5452e398b76 889
Just4pLeisure 1:d5452e398b76 890 //-----------------------------------------------------------------------------
Just4pLeisure 1:d5452e398b76 891 // EOF
Just4pLeisure 1:d5452e398b76 892 //-----------------------------------------------------------------------------