Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: bdmtrionic.cpp
- Revision:
- 4:682d96ff6d79
- Parent:
- 2:bf3a2b29259a
- Child:
- 5:1775b4b13232
diff -r 92dae9083c83 -r 682d96ff6d79 bdmtrionic.cpp
--- a/bdmtrionic.cpp Tue Jun 07 12:23:28 2011 +0000
+++ b/bdmtrionic.cpp Wed Sep 11 11:55:51 2013 +0000
@@ -80,7 +80,8 @@
*/
-uint8_t dump_flash(const uint32_t* start_addr, const uint32_t* end_addr) {
+uint8_t dump_flash(const uint32_t* start_addr, const uint32_t* end_addr)
+{
// check parametres
if (*start_addr > *end_addr) {
@@ -105,6 +106,7 @@
// send memory value to host
printf("%08X", value);
+ printf("\r\n");
// add the terminating character
if (curr_addr < *end_addr - 4) {
@@ -131,7 +133,8 @@
@return status flag
*/
-uint8_t dump_trionic() {
+uint8_t dump_trionic()
+{
// Configure the MC68332 register values to prepare for flashing
printf("I am trying to discover what type of Trionic ECU I am connected to...\r\n");
@@ -145,6 +148,11 @@
uint32_t flash_size;
switch (type) {
+ case AMD29BL802C:
+ printf("I have found AMD29BL802C type FLASH chips; I must be connected to a T8 ECU :-)\r\n");
+ reset_func = &reset_am29;
+ flash_size = T8FLASHSIZE;
+ break;
case AMD29F400B:
case AMD29F400T:
printf("I have found AMD29F400 type FLASH chips; I must be connected to a T7 ECU :-)\r\n");
@@ -193,7 +201,7 @@
timer.reset();
timer.start();
-
+ printf(" 0.00 %% complete.\r");
while (addr < flash_size) {
uint16_t byte_count = 0;
while (byte_count < FILE_BUF_LENGTH) {
@@ -207,7 +215,7 @@
file_buffer[byte_count+3] = ((uint8_t)long_value);
byte_count +=4;
// make the activity led twinkle
- ACTIVITYLEDON;
+ ACTIVITYLEDON;
}
fwrite(file_buffer, 1, FILE_BUF_LENGTH, fp);
if (ferror (fp)) {
@@ -215,7 +223,9 @@
printf ("Error writing to the FLASH BIN file.\r\n");
return TERM_ERR;
}
+ printf("%6.2f\r", 100*(float)addr/(float)flash_size );
}
+ printf("\n");
// should 'clear' the BDM connection here but bdm_clear won't compile from here
// instead do a memread (or anything really) but ignore the result because it's not needed for anything
memread_long(&long_value, &addr);
@@ -238,7 +248,8 @@
@return status flag
*/
uint8_t erase_flash(const char* flash_type, const uint32_t* start_addr,
- const uint32_t* end_addr) {
+ const uint32_t* end_addr)
+{
// AM29Fxxx chips (retrofitted to Trionic 5.x; original to T7)
if (strncmp(flash_type, "29f010", 6) == 0 ||
strncmp(flash_type, "29f400", 6) == 0) {
@@ -264,7 +275,8 @@
@return status flag
*/
-uint8_t write_flash(const char* flash_type, const uint32_t* start_addr) {
+uint8_t write_flash(const char* flash_type, const uint32_t* start_addr)
+{
// set up chip-specific functions
bool (*reset_func)(void);
bool (*flash_func)(const uint32_t*, uint16_t);
@@ -349,7 +361,7 @@
curr_addr += 2;
// light up the activity LED
- ACTIVITYLEDON;
+ ACTIVITYLEDON;
}
// reset flash
@@ -367,7 +379,8 @@
@return status flag
*/
-uint8_t flash_trionic() {
+uint8_t flash_trionic()
+{
// Configure the MC68332 register values to prepare for flashing
printf("I am trying to discover what type of Trionic ECU I am connected to...\r\n");
prep_t5_do();
@@ -381,6 +394,12 @@
uint32_t flash_size;
switch (type) {
+ case AMD29BL802C:
+ printf("I have found AMD29BL802C type FLASH chips; I must be connected to a T8 ECU :-)\r\n");
+ reset_func = &reset_am29;
+ flash_func = &flash_am29;
+ flash_size = T8FLASHSIZE;
+ break;
case AMD29F400B:
case AMD29F400T:
printf("I have found AMD29F400 type FLASH chips; I must be connected to a T7 ECU :-)\r\n");
@@ -415,6 +434,7 @@
}
// reset the FLASH chips
+ printf("Reset the FLASH chip(s) to prepare them for Erasing\r\n");
if (!reset_func()) return TERM_ERR;
printf("Checking the FLASH BIN file...\r\n");
@@ -459,6 +479,12 @@
printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, flash_size, stack_long);
return TERM_ERR;
}
+ if (flash_size == T8FLASHSIZE && (file_size != T8FLASHSIZE || stack_long != T8POINTER)) {
+ fclose(fp);
+ printf("The BIN file does not appear to be for a T8 ECU :-(\r\n");
+ printf("BIN file size: %#10x, FLASH chip size: %#010x, Pointer: %#10x.\r\n", file_size, flash_size, stack_long);
+ return TERM_ERR;
+ }
timer.reset();
timer.start();
@@ -467,10 +493,11 @@
switch (type) {
// AM29Fxxx chips (retrofitted to Trionic 5.x; original to T7)
+ case AMD29BL802C:
case AMD29F400B:
case AMD29F400T:
case AMD29F010:
- printf("Erasing 29F400/010 type FLASH chips...\r\n");
+ printf("Erasing 29BL802/F400/010 type FLASH chips...\r\n");
if (!erase_am29()) {
printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n");
return TERM_ERR;
@@ -488,7 +515,7 @@
}
break;
default:
- // unknown flash type - shouldn't get here hence "Starange!"
+ // unknown flash type - shouldn't get here hence "Strange!"
printf("Strange! I couldn't work out how to erase the FLASH chips in the TRIONIC ECU that I am connected to :-(\r\n");
return TERM_ERR;
}
@@ -506,6 +533,7 @@
// bool ret = true;
// ready to receive data
+ printf(" 0.00 %% complete.\r");
while (curr_addr < flash_size) {
// receive bytes from BIN file
//Get a byte - break if no more bytes to get
@@ -529,40 +557,46 @@
curr_addr += 2;
// make the activity LED twinkle
- ACTIVITYLEDON;
+ ACTIVITYLEDON;
+ if (!(curr_addr % 0x80))
+ printf("%6.2f\r", 100*(float)curr_addr/(float)flash_size );
}
-
+ printf("\n");
timer.stop();
fclose(fp);
if (curr_addr == flash_size) {
printf("Programming took %#.1f seconds.\r\n",timer.read());
- reset_func();
- for (uint8_t i = 0; i < 8; ++i) {
- memread_word(&word_value, &flash_tag[i].addr);
- flash_func(&flash_tag[i].addr, (flash_tag[i].val & word_value));
- }
- } else {
+ // "Just4pleisure;)" 'tag' in the empty space at the end of the FLASH chip
+ // Removed for now because it conflicts with some information that Dilemma places in this empty space
+ // and because it is unsafe for Trionic 8 ECUs which have much bigger BIN files and FLASH chips
+ // reset_func();
+ // for (uint8_t i = 0; i < 8; ++i) {
+ // memread_word(&word_value, &flash_tag[i].addr);
+ // flash_func(&flash_tag[i].addr, (flash_tag[i].val & word_value));
+ // }
+
+ } else
printf("WARNING: Oh dear, I couldn't program the FLASH at address 0x%8x.\r\n", curr_addr);
- }
-// reset flash
+ // reset flash
return (reset_func() && (curr_addr == flash_size)) ? TERM_OK : TERM_ERR;
}
//-----------------------------------------------------------------------------
/**
- Resets an AM29Fxxx flash memory chip. MCU must be in background mode.
+Resets an AM29Fxxx flash memory chip. MCU must be in background mode.
- @param none
+@param none
- @return succ / fail
+@return succ / fail
*/
-bool reset_am29(void) {
+bool reset_am29(void)
+{
// execute the reset command
-// uint32_t addr = 0xfffe;
-// return (memwrite_word(&addr, 0xf0f0) == TERM_OK);
+ // uint32_t addr = 0xfffe;
+ // return (memwrite_word(&addr, 0xf0f0) == TERM_OK);
// execute the algorithm
for (uint8_t i = 0; i < 3; ++i) {
if (memwrite_word(&am29_reset[i].addr, am29_reset[i].val) != TERM_OK) return false;
@@ -572,17 +606,20 @@
//-----------------------------------------------------------------------------
/**
- Erases an AM29Fxxx flash memory chip and verifies the result; MCU must be
- in background mode.
+Erases an AM29Fxxx flash memory chip and verifies the result; MCU must be
+in background mode.
- @return succ / fail
+@return succ / fail
*/
-bool erase_am29() {
+bool erase_am29()
+{
// reset flash
if (!reset_am29()) {
return false;
}
-
+ printf("Erasing AMD 29Fxxx FLASH chips.\r\n");
+ printf("This can take up to a minute for a T8,\r\n");
+ printf("30s for a T7 or 15s for a T5 ECU.\r\n");
// execute the algorithm
for (uint8_t i = 0; i < 6; ++i) {
if (memwrite_word(&am29_erase[i].addr, am29_erase[i].val) != TERM_OK) {
@@ -595,17 +632,24 @@
uint32_t addr = 0x0;
uint16_t verify_value;
+ printf(" 0.0 seconds.\r");
uint8_t err_cnt = ERR_COUNT;
while (--err_cnt) {
// typical erase time = 1s
// Allow up to 25.5 seconds erase time
wait_ms(100);
+ wait_ms(100);
if (memread_word(&verify_value, &addr) == TERM_OK && verify_value == 0xffff) {
// erase completed normally
reset_am29();
+ printf("\n");
return true;
}
+ // make the activity LED twinkle
+ ACTIVITYLEDON;
+ printf("%4.1f\r", (float)ERR_COUNT/5 - (float)err_cnt/5 );
}
+ printf("\n");
// erase failed
reset_am29();
@@ -614,15 +658,16 @@
//-----------------------------------------------------------------------------
/**
- Writes a word to AM29Fxxx flash memory chip and optionally verifies the
- result; MCU must be in background mode.
+Writes a word to AM29Fxxx flash memory chip and optionally verifies the
+result; MCU must be in background mode.
- @param addr destination address
- @param val value
+@param addr destination address
+@param val value
- @return succ / fail
+@return succ / fail
*/
-bool flash_am29(const uint32_t* addr, uint16_t value) {
+bool flash_am29(const uint32_t* addr, uint16_t value)
+{
// execute the algorithm
for (uint8_t i = 0; i < 3; ++i) {
@@ -640,7 +685,8 @@
uint8_t err_cnt = ERR_COUNT;
while (--err_cnt) {
// Allow up to approx 2.55 milliseconds program time (255 * ~10us BDM memread time)
-// wait_ms(10);
+ // wait_ms(10);
+ wait_us(100);
uint16_t verify_value;
if ((memread_word(&verify_value, addr) == TERM_OK) &&
(verify_value == value)) {
@@ -655,28 +701,30 @@
//-----------------------------------------------------------------------------
/**
- Resets a AM28Fxxx flash memory chip. MCU must be in background mode.
+Resets a AM28Fxxx flash memory chip. MCU must be in background mode.
- @param start_addr flash start address
+@param start_addr flash start address
- @return succ / fail
+@return succ / fail
*/
-bool reset_am28(void) {
+bool reset_am28(void)
+{
uint32_t start_addr = 0x0;
return (memwrite_word_write_word(&start_addr, 0xffff, 0xffff) == TERM_OK);
}
//-----------------------------------------------------------------------------
/**
- Erases an AM28Fxxx flash memory chip and verifies the result; MCU must be
- in background mode.
+Erases an AM28Fxxx flash memory chip and verifies the result; MCU must be
+in background mode.
- @param start_addr flash start address
- @param end_addr flash end address
+@param start_addr flash start address
+@param end_addr flash end address
- @return succ / fail
+@return succ / fail
*/
-bool erase_am28(const uint32_t* start_addr, const uint32_t* end_addr) {
+bool erase_am28(const uint32_t* start_addr, const uint32_t* end_addr)
+{
// check the addresses
if (!start_addr || !end_addr) return false;
@@ -687,20 +735,26 @@
// write zeroes over entire flash space
uint32_t addr = *start_addr;
+ printf("First write 0x00 to all FLASH addresses.\r\n");
+ printf(" 0.00 %% complete.\r");
while (addr < *end_addr) {
if (!flash_am28(&addr, 0x0000)) return false;
addr += 2;
-// // feedback to host computer
-// pc.putc(TERM_OK);
+ // // feedback to host computer
+ // pc.putc(TERM_OK);
// make the activity LED twinkle
- ACTIVITYLEDON;
-
+ ACTIVITYLEDON;
+ if (!(addr % 0x80))
+ printf("%6.2f\r", 100*(float)addr/(float)*end_addr );
}
+ printf("\n");
// erase flash
addr = *start_addr;
uint8_t verify_value;
+ printf("Now erasing FLASH and verfiying that all addresses are 0xFF.\r\n");
+ printf(" 0.00 %% complete.\r");
uint16_t pulse_cnt = 0;
if (memwrite_byte_cmd(NULL) != TERM_OK) {
reset_am28();
@@ -715,16 +769,19 @@
while (addr < *end_addr) {
// issue the verify command
if (memwrite_read_byte(&addr, 0xa0) != TERM_OK) break;
-// wait_us(6);
+ // wait_us(6);
// check the written value
if (memread_write_byte(&verify_value, &addr) != TERM_OK) break;
if (verify_value != 0xff) break;
// succeeded need to check next address
addr++;
// make the activity LED twinkle
- ACTIVITYLEDON;
+ ACTIVITYLEDON;
+ if (!(addr % 0x80))
+ printf("%6.2f\r", 100*(float)addr/(float)*end_addr );
}
}
+ printf("\n");
// the erase process ends with a BDM_WRITE + BDM_BYTESIZE command left in the BDM
// it is safe to use it to put one of the FLASH chips into read mode and thereby
// leave the BDM ready for the next command
@@ -737,17 +794,18 @@
//-----------------------------------------------------------------------------
/**
- Writes a byte to AM28Fxxx flash memory chip and verifies the result
- A so called 'mask' method checks the FLASH contents and only tries
- to program bytes that need to be programmed.
- MCU must be in background mode.
+Writes a byte to AM28Fxxx flash memory chip and verifies the result
+A so called 'mask' method checks the FLASH contents and only tries
+to program bytes that need to be programmed.
+MCU must be in background mode.
- @param addr destination address
- @param val value
+@param addr destination address
+@param val value
- @return succ / fail
+@return succ / fail
*/
-bool flash_am28(const uint32_t* addr, uint16_t value) {
+bool flash_am28(const uint32_t* addr, uint16_t value)
+{
if (!addr) return false;
@@ -785,16 +843,18 @@
//-----------------------------------------------------------------------------
/**
- Does the equivalent of do prept5.do in BD32
- Sets up all of the control registers in the MC68332 so that we can program
- the FLASH chips
+Does the equivalent of do prept5.do in BD32
+Sets up all of the control registers in the MC68332 so that we can program
+the FLASH chips
- @param none
+@param none
- @return succ / fail
+@return succ / fail
*/
-uint8_t prep_t5_do(void) {
+//uint8_t prep_t5_do(void) {
+uint8_t prep_t8_do(void)
+{
// reset and freeze the MC68332 chip
if (restart_chip() != TERM_OK) return TERM_ERR;
@@ -804,48 +864,138 @@
if (sysreg_write(0x0e, &long_value) != TERM_OK) return TERM_ERR;
if (sysreg_write(0x0f, &long_value) != TERM_OK) return TERM_ERR;
- // Set MC68332 to 16 MHz (actually 16.78 MHz)
+ // Set MC68332 to 16 MHz (actually 16.78 MHz) (SYNCR)
long_value = 0x00fffa04;
if (memwrite_word(&long_value, 0x7f00) != TERM_OK) return TERM_ERR;
- // Disable watchdog and monitors
+ // Disable watchdog and monitors (SYPCR)
long_value = 0x00fffa21;
if (memwrite_byte(&long_value, 0x00) != TERM_OK) return TERM_ERR;
- // Chip select pin assignments
+
+ // Chip select pin assignments (CSPAR0)
long_value = 0x00fffa44;
if (memwrite_word(&long_value, 0x3fff) != TERM_OK) return TERM_ERR;
- // Boot Chip select read only, one wait state
+ // Boot Chip select read only, one wait state (CSBARBT)
long_value = 0x00fffa48;
if (memwrite_word(&long_value, 0x0007) != TERM_OK) return TERM_ERR;
if (memfill_word(0x6870) != TERM_OK) return TERM_ERR;
- // Chip select 1 and 2 upper lower bytes, zero wait states
+ // Chip select 1 and 2 upper lower bytes, zero wait states (CSBAR1, CSOR1, CSBAR2, CSBAR2)
long_value = 0x00fffa50;
if (memwrite_word(&long_value, 0x0007) != TERM_OK) return TERM_ERR;
if (memfill_word(0x3030) != TERM_OK) return TERM_ERR;
if (memfill_word(0x0007) != TERM_OK) return TERM_ERR;
if (memfill_word(0x5030) != TERM_OK) return TERM_ERR;
- // PQS Data - turn on VPPH
+ // PQS Data - turn on VPPH (PORTQS)
long_value = 0x00fffc14;
if (memwrite_word(&long_value, 0x0040) != TERM_OK) return TERM_ERR;
- // PQS Data Direction output
+ // PQS Data Direction output (DDRQS)
long_value = 0x00fffc17;
if (memwrite_byte(&long_value, 0x40) != TERM_OK) return TERM_ERR;
// wait for programming voltage to be ready
wait_ms(10);
-// // Enable internal 2kByte RAM of 68332 at address 0x00100000
-// long_value = 0x00fffb04;
-// if (memwrite_word(&long_value, 0x1000) != TERM_OK) return TERM_ERR;
+ // // Enable internal 2kByte RAM of 68332 at address 0x00100000 (TRAMBAR)
+ // long_value = 0x00fffb04;
+ // if (memwrite_word(&long_value, 0x1000) != TERM_OK) return TERM_ERR;
return TERM_OK;
}
//-----------------------------------------------------------------------------
/**
+Does the equivalent of do prept5/7/8.do in BD32
+Sets up all of the control registers in the MC68332/377 so that we can
+program the FLASH chips
+
+@param none
+
+@return succ / fail
+*/
+
+uint8_t prep_t5_do(void)
+{
+
+ // reset and freeze the MC68332/377 chip
+ if (restart_chip() != TERM_OK) return TERM_ERR;
+
+ // define some variables to store address and data values
+ uint32_t long_value = 0x05;
+ uint16_t verify_value;
+
+ // set the 'fc' registers to allow supervisor mode access
+ if (sysreg_write(0x0e, &long_value) != TERM_OK) return TERM_ERR;
+ if (sysreg_write(0x0f, &long_value) != TERM_OK) return TERM_ERR;
+
+ // Read MC68332/377 Module Control Register (SIMCR/MCR)
+ // and use the value to work out if ECU is a T5/7 or a T8
+ long_value = 0x00fffa00;
+ if (memread_word(&verify_value, &long_value) != TERM_OK) return TERM_ERR;
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// verify_value = 0x7E4F;
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // MC68377 MCR = x111111x01001111 binary after a reset
+ if ((verify_value & 0x7E4F) == 0x7E4F) {
+ printf ("I have found a Trionic 8 ECU.\r\n");
+// Set MC68377 to double it's default speed (16 MHz?) (SYNCR)
+ long_value = 0x00fffa08;
+ // First set the MFD part (change 4x to 8x)
+ if (memwrite_word(&long_value, 0x6908) != TERM_OK) return TERM_ERR;
+ // wait for everything to settle (should really check the PLL lock register)
+ wait_ms(100);
+ // Now set the RFD part (change /2 to /1)
+ if (memwrite_word(&long_value, 0x6808) != TERM_OK) return TERM_ERR;
+ // Disable watchdog and monitors (SYPCR)
+ long_value = 0x00fffa50;
+ if (memwrite_word(&long_value, 0x0000) != TERM_OK) return TERM_ERR;
+ return TERM_OK;
+ }
+// MC68332 SIMCR = 0000x00011001111 binary after a reset
+ //if ((verify_value & 0x00CF) == 0x00CF) {
+ else {
+ printf ("I have found a Trionic 5 or 7 ECU.\r\n");
+ // Set MC68332 to 16 MHz (actually 16.78 MHz) (SYNCR)
+ long_value = 0x00fffa04;
+ if (memwrite_word(&long_value, 0x7f00) != TERM_OK) return TERM_ERR;
+ // Disable watchdog and monitors (SYPCR)
+ long_value = 0x00fffa21;
+ if (memwrite_byte(&long_value, 0x00) != TERM_OK) return TERM_ERR;
+ // Chip select pin assignments (CSPAR0)
+ long_value = 0x00fffa44;
+ if (memwrite_word(&long_value, 0x3fff) != TERM_OK) return TERM_ERR;
+ // Boot Chip select read only, one wait state (CSBARBT)
+ long_value = 0x00fffa48;
+ if (memwrite_word(&long_value, 0x0007) != TERM_OK) return TERM_ERR;
+ if (memfill_word(0x6870) != TERM_OK) return TERM_ERR;
+ // Chip select 1 and 2 upper lower bytes, zero wait states (CSBAR1, CSOR1, CSBAR2, CSBAR2)
+ long_value = 0x00fffa50;
+ if (memwrite_word(&long_value, 0x0007) != TERM_OK) return TERM_ERR;
+ if (memfill_word(0x3030) != TERM_OK) return TERM_ERR;
+ if (memfill_word(0x0007) != TERM_OK) return TERM_ERR;
+ if (memfill_word(0x5030) != TERM_OK) return TERM_ERR;
+ // PQS Data - turn on VPPH (PORTQS)
+ long_value = 0x00fffc14;
+ if (memwrite_word(&long_value, 0x0040) != TERM_OK) return TERM_ERR;
+ // PQS Data Direction output (DDRQS)
+ long_value = 0x00fffc17;
+ if (memwrite_byte(&long_value, 0x40) != TERM_OK) return TERM_ERR;
+ // wait for programming voltage to be ready
+ wait_ms(10);
+ // Enable internal 2kByte RAM of 68332 at address 0x00100000 (TRAMBAR)
+ //long_value = 0x00fffb04;
+ //if (memwrite_word(&long_value, 0x1000) != TERM_OK) return TERM_ERR;
+ return TERM_OK;
+ }
+// Unknown MC683xx chip if code reaches this point
+ return TERM_ERR;
+}
+
+
+//-----------------------------------------------------------------------------
+/**
Works out what type of flash chip is fitted in the ECU by reading
the manufacturer byte codes.
It is enough to use the 29Fxxx flash id algorithm because 28Fxxx
@@ -857,22 +1007,31 @@
@return succ / fail
*/
-bool get_flash_id(uint8_t* make, uint8_t* type) {
+bool get_flash_id(uint8_t* make, uint8_t* type)
+{
uint32_t addr = 0x0;
uint32_t value;
bool ret;
// read id bytes algorithm for 29F010/400 FLASH chips
for (uint8_t i = 0; i < 3; ++i) {
- if (memwrite_word(&am29_id[i].addr, am29_id[i].val) != TERM_OK) return false;
+ //printf("Getting FLASH chip ID.\r\n");
+ if (memwrite_word(&am29_id[i].addr, am29_id[i].val) != TERM_OK) {
+ printf("There was an error when I tried to request the FLASH chip ID.\r\n");
+ return false;
+ }
}
- if (memread_long(&value, &addr) != TERM_OK) return false;
+ if (memread_long(&value, &addr) != TERM_OK) {
+ printf("Error Reading FLASH chip types in get_flash_id\r\n");
+ return false;
+ }
// *make = (uint8_t)(value >> 24);
// *type = (uint8_t)(value >> 8);
*make = (uint8_t)(value >> 16);
*type = (uint8_t)(value);
printf("FLASH id bytes: %08x, make: %02x, type: %02x\r\n", value, *make, *type);
switch (*type) {
+ case AMD29BL802C:
case AMD29F400B:
case AMD29F400T:
case AMD29F010: