Just4Trionic - CAN and BDM FLASH programmer for Saab cars

Dependencies:   mbed

Revision:
4:682d96ff6d79
Parent:
2:bf3a2b29259a
Child:
5:1775b4b13232
--- 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: