Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Committer:
Just4pLeisure
Date:
Tue Sep 14 21:02:04 2010 +0000
Revision:
1:d5452e398b76
Child:
2:bf3a2b29259a

        

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