Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Flash Mem Soldering Help

  1. #1
    Member Dionysus's Avatar
    Join Date
    Apr 2020
    Location
    Chicago
    Posts
    32

    Flash Mem Soldering Help

    Specs: Teensy 4.0 with Audio shield Rev D and a W25Q126JVSIQ-ND memory chip from digi-key.

    I am still struggling to get this working; just about the last piece of my puzzle. I was getting Erase Everything to work, but couldn't get RawHardwareTest's full approval. So I used solder braid to desolder everything, pried off the chip, and cleaned everything up with alcohol.

    I put a drop of soldern on each of the six contacts, and then positioned a fresh clean chip (also from digikey) over it and heated down all six legs until the solder melted and it was stuck on.

    That didn't do anything—EraseEverything no longer erases anything, it just says "Unable to access SPI Flash chip".

    So I added some more solder to the tops of the legs, but that didn't do anything except make it look messier. Nothing looks like it's bridging, but EraseEverything is still refusing to play.

    I've ordered a brand new AudioShield, and I have one remaining memory chip. I really want to get this to work! Can you recommend anything I should do differently this time?

    I'm just using the standard example EraseEverything, but I'll post it here just in case. Thanks again for all your help with this. It's just frustrating because I don't even really know how to debug what's wrong.

    Click image for larger version. 

Name:	IMG_20200527_170440.jpg 
Views:	23 
Size:	70.7 KB 
ID:	20316


    Code:
    #include <SerialFlash.h>
    #include <SPI.h>
    
    const int FlashChipSelect = 6; // digital pin for flash chip CS pin
    //const int FlashChipSelect = 21; // Arduino 101 built-in SPI Flash
    
    SerialFlashFile file;
    
    const unsigned long testIncrement = 4096;
    
    void setup() {
      //uncomment these if using Teensy audio shield
      //SPI.setSCK(14);  // Audio shield has SCK on pin 14
      //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
    
      //uncomment these if you have other SPI chips connected
      //to keep them disabled while using only SerialFlash
      //pinMode(4, INPUT_PULLUP);
      //pinMode(10, INPUT_PULLUP);
    
      Serial.begin(9600);
    
      // wait up to 10 seconds for Arduino Serial Monitor
      unsigned long startMillis = millis();
      while (!Serial && (millis() - startMillis < 10000)) ;
      delay(100);
    
      if (!SerialFlash.begin(FlashChipSelect)) {
        while (1) {
          Serial.println("Unable to access SPI Flash chip");
          delay(1000);
        }
      }
      unsigned char id[5];
      SerialFlash.readID(id);
      unsigned long size = SerialFlash.capacity(id);
    
      if (size > 0) {
        Serial.print("Flash Memory has ");
        Serial.print(size);
        Serial.println(" bytes.");
        Serial.println("Erasing ALL Flash Memory:");
        // Estimate the (lengthy) wait time.
        Serial.print("  estimated wait: ");
        int seconds = (float)size / eraseBytesPerSecond(id) + 0.5;
        Serial.print(seconds);
        Serial.println(" seconds.");
        Serial.println("  Yes, full chip erase is SLOW!");
        SerialFlash.eraseAll();
        unsigned long dotMillis = millis();
        unsigned char dotcount = 0;
        while (SerialFlash.ready() == false) {
          if (millis() - dotMillis > 1000) {
            dotMillis = dotMillis + 1000;
            Serial.print(".");
            dotcount = dotcount + 1;
            if (dotcount >= 60) {
              Serial.println();
              dotcount = 0;
            }
          }
        }
        if (dotcount > 0) Serial.println();
        Serial.println("Erase completed");
        unsigned long elapsed = millis() - startMillis;
        Serial.print("  actual wait: ");
        Serial.print(elapsed / 1000ul);
        Serial.println(" seconds.");
      }
    }
    
    float eraseBytesPerSecond(const unsigned char *id) {
      if (id[0] == 0x20) return 152000.0; // Micron
      if (id[0] == 0x01) return 500000.0; // Spansion
      if (id[0] == 0xEF) return 419430.0; // Winbond
      if (id[0] == 0xC2) return 279620.0; // Macronix
      return 320000.0; // guess?
    }
    
    
    void loop() {
    
    }

  2. #2
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,199
    The chip looks to be oriented right.

    Is Flux paste/fluid handy? A small dab after can reflow better on each pin making sure to heat pin and pad both with a clean tip for true solder connect.
    Have you cleaned off the flux? Here a toothbrush wet with 90% Isopropyl on just that chip corner soften and remove flux works. Then brush again with clean Iso. pat/shake dry - hit with a hairdryer to heat and blow out trapped liquid while moving/flipping - heat a minute while still hold-able in hand - check for no fluid - allow to cool and dry before powering. 70% should work as well - but I have 90% there that evaporates and may clean better depending on the flux type.

    Using post #1 code - TD 1.52 with IDE 1.8.12 on Windows it worked on a T_4.0 with a Rev Audio board with a winbond chips soldered on. So that is the right software setup:
    Code:
    Flash Memory has 16777216 bytes.
    Erasing ALL Flash Memory:
      estimated wait: 40 seconds.
      Yes, full chip erase is SLOW!
    ..........................................
    Erase completed
      actual wait: 42 seconds.
    Then loaded RawHardwareTest - unchanged from install:
    Code:
    Raw SerialFlash Hardware Test
    
    Read Chip Identification:
      JEDEC ID:     EF 40 18
      Part Nummber: W25Q128FV
      Memory Size:  16777216 bytes
      Block Size:   65536 bytes
    
    Reading Chip...
    
    Writing 8192 signatures
    
    Double Checking All Signatures:
      all 8192 signatures read ok
    
    Checking Signature Pairs
      all 4095 signature pairs read ok
    
    Checking Read-While-Write (Program Suspend)
      write 256 bytes at 256
      write time was 374 microseconds.
      read-while-writing: 00 00 00 00 15 F5 95 4B 
      test passed, good read while writing
    
    Checking Read-While-Erase (Erase Suspend)
      erase time was 177112 microseconds.
      erase correctly erased 65536 bytes
      read-while-erasing: 00 00 00 00 15 F5 95 4B 
      test passed, good read while erasing
    
    All Tests Passed  :-)
    
    Test data was written to your chip.  You must run
    EraseEverything before using this chip for files.
    Then returned to EraseEverything and all is well.

  3. #3
    Senior Member
    Join Date
    Mar 2016
    Posts
    200
    Putting solder on all the pads before hand makes it hard to get good contact. I've done a lot of SMDs by hand and this technique works for me. Use a pair of fine tweezers and a small iron tip.
    - flux pen to coat all pads. You don't need a lot.
    - dab of solder on one corner pad
    - touch the iron next to that pad and slide the IC in place when the solder melts. Position the iron so when the IC lead hits the tip it is in place.
    - make sure the IC is properly aligned and remove the iron while holding the IC in place till the solder cools. make sure the IC is flat against the PCB.
    - double check alignment - fix if not right.
    - solder the rest of the IC leads. You put a blob of solder on the tip of the iron, touch it to each lead and draw outward along the lead. I can get several leads per blob. Don't worry about bridges while doing it.
    - solder wick and iron to clean up any bridges.
    - inspect with microscope or magnifier. fix any suspect joints.
    - clean flux with Isopropyl or similar. Toothbrush is a good tool.

  4. #4
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,199
    @PhilB - looks good. I never tinned the pads for reason mentioned - assuring flat contact for all legs.

    Chips can be tricky with tweezers - but that 'slide' works. Last one (pair of smaller PSRAMs on T_4.1) from another suggestion was done clear taping it to the board and it worked about as well - but tended to shift the chip as I secured the tape to PCB - so only good is that can't burn oneself redoing the tape to perfection - and then both hands are free to solder exposed half of chip, and can take a shaky tweezer hand doing slide out of the process.

    And the final 'cleaning' step can be the critical part for proper function even if all else done well.

    I ended up with a small tub of flux paste. Flux pens I got first few times would trigger a flood of too much - then the next time needed it was empty.

  5. #5
    Senior Member
    Join Date
    Mar 2016
    Posts
    200
    I have some really nice tweezers - no name but very thin - makes it super easy to mount even SOT-23s and such. I have a home brew vacuum pick/place set up. It works quite well if doing reflow but for manual soldering tweezers are my go to tool.

    I used to use flux with an applicator but always got too much no matter how light a touch I tried. Don't know what to say, my pens have always been stingy - to point I will dribble a little isopropyl in it. A spare coating is all it takes and makes clean up a lot easier. My current one is from MG Chemicals.

    Here's an example of one I did by hand with the iron/tweezers technique. Even the tssops came out ok.
    Click image for larger version. 

Name:	PCB V100.jpg 
Views:	19 
Size:	143.9 KB 
ID:	20340

  6. #6
    Member Dionysus's Avatar
    Join Date
    Apr 2020
    Location
    Chicago
    Posts
    32
    Ok, reflowing and cleaning worked wonders! If I've learned nothing else from this, "the final 'cleaning' step can be the critical part for proper function even if all else done well" is a great takeaway, thank you!

    So now it works unless I put in an SD card. Without the card, I get an "All tests passed" from RawHardwareTest (see below). But if there is an SD card in the audio shield drive, even though EraseEverything and CopyFromSDCard both work, it fails the RawHardwareTest (see below, as well).

    Also, when I plug in the touchscreen , EraseEverything and CopyFromSDCard no longer work. Surely this must mean something, right?! (:


    Here's the results with no SD card in the drive:

    Code:
    Raw SerialFlash Hardware Test
    
    
    
    Read Chip Identification:
    
      JEDEC ID:     EF 40 18
    
      Part Nummber: W25Q128FV
    
      Memory Size:  16777216 bytes
    
      Block Size:   65536 bytes
    
    
    
    Reading Chip...
    
    
    
    Writing 8192 signatures
    
    
    
    Double Checking All Signatures:
    
      all 8192 signatures read ok
    
    
    
    Checking Signature Pairs
    
      all 4095 signature pairs read ok
    
    
    
    Checking Read-While-Write (Program Suspend)
    
      write 256 bytes at 256
    
      write time was 377 microseconds.
    
      read-while-writing: 00 00 00 00 15 F5 95 4B 
    
      test passed, good read while writing
    
    
    
    Checking Read-While-Erase (Erase Suspend)
    
      erase time was 147290 microseconds.
    
      erase correctly erased 65536 bytes
    
      read-while-erasing: 00 00 00 00 15 F5 95 4B 
    
      test passed, good read while erasing
    
    
    
    All Tests Passed  :-)
    
    
    
    Test data was written to your chip.  You must run
    
    EraseEverything before using this chip for files.
    Then I put an SD card in and ran EraseEverything. It took 22 seconds (both with and without an SD card), and then RawHardwareTest gave me this:
    Code:
    Raw SerialFlash Hardware Test
    
    
    
    Read Chip Identification:
    
      JEDEC ID:     EF 40 18
    
      Part Nummber: W25Q128FV
    
      Memory Size:  16777216 bytes
    
      Block Size:   65536 bytes
    
    
    
    Reading Chip...
    
    
    
    Writing 8192 signatures
    
      error writing signature at 3395576
    
      Read this: 00 00 00 00 00 00 00 00 
    
      Expected:  00 33 CF F8 8B FA FB 5F 
    
    
    
    Tests Failed  :{
    
    
    
    The flash chip may be left in an improper state.
    
    You might need to power cycle to return to normal.
    Also, when I plug in the touchscreen, EraseEverything takes 0 seconds, and RawHardwareTest gives me this:

    Code:
    Raw SerialFlash Hardware Test
    
    
    
    Read Chip Identification:
    
      JEDEC ID:     6F 40 18
    
      Part Nummber: (unknown chip)
    
      Memory Size:  16777216 bytes
    
      Block Size:   65536 bytes
    
    
    
    Reading Chip...
    
      Previous data found at address 0
    
      You must fully erase the chip before this test
    
      found this: 00 00 00 00 00 00 00 00 
    
         correct: 00 00 00 00 15 F5 95 4B 
    
    
    
    Tests Failed  :{
    
    
    
    The flash chip may be left in an improper state.
    
    You might need to power cycle to return to normal.
    Just to make this post as verbose as I possibly can, here are the pins I'm using for the touchscreen:
    Pin 7: Audio DIN
    Pin 8: Touch Interface CS
    Pin 9: Display D/C
    Pin 10: Audio SD CS
    Pin 11: Touch Interface DIN and also Display MOSI
    Pin 12: Touch Interface DO and also Diaplay MISO
    Pin 13: Display SCK and also Touch Interface CLK (and also the Audio SCK, as well, it is ok to use this pin for all of that?)
    Pin 14: Display CS


    Thank you to everyone for you patience and advice in helping me debug this thing! I feel like I'm right on the edge of getting everything to work, but I'm just missing one thing.

  7. #7
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,199
    Quote Originally Posted by Dionysus View Post
    Ok, reflowing and cleaning worked wonders! If I've learned nothing else from this, "the final 'cleaning' step can be the critical part for proper function even if all else done well" is a great takeaway, thank you!

    So now it works unless I put in an SD card. Without the card, I get an "All tests passed" from RawHardwareTest (see below). But if there is an SD card in the audio shield drive, even though EraseEverything and CopyFromSDCard both work, it fails the RawHardwareTest (see below, as well).
    ...

    Thank you to everyone for you patience and advice in helping me debug this thing! I feel like I'm right on the edge of getting everything to work, but I'm just missing one thing.
    Great that worked - glad you didn't break anything pulling the other chip off - and didn't give up.

    Not able to confirm SD and FLASH function just now though ...

    SPI is a common wire bus for SCK/CLK and MOSI and MISO - and to own the bus each device gets its own CS. Just need to be sure the CS's in use aren't in conflict with other uses.

  8. #8
    Member Dionysus's Avatar
    Join Date
    Apr 2020
    Location
    Chicago
    Posts
    32
    Quote Originally Posted by defragster View Post
    Just need to be sure the CS's in use aren't in conflict with other uses.
    So, I've wired Pin 9 to the T_CS pin on the touchscreen, and pin 14 to the display CS pin. I'm sorry if this is a dumb question, but when I run EraseEverything I haven't actually done anything with those pins—they aren't mentioned in the code at all. Do I need to initialize the touchscreen in order to make sure that it knows what its CS is? Or do I need to tell the flash chip that it should relinquish control when the touchscreen needs it?

    Same question about the audio shield and its SD card CS. I haven't actually told it to pay attention to pin 10. However, if sounds like you were able to get things to work with the audio shield + sd card and only that same code, so I guess that's not the answer.

  9. #9
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    12,199
    Board pin info ref: pjrc.com/store/teensy3_audio.html

    Prior note was to say - it is expected to work - but not in a place to try it here just now.

    If a CS pin is not set HIGH a device on the common bus will still be powered and it may interfere with other devices on that bus.

    There is good background on this Paul Blog page : pjrc.com/better-spi-bus-design-in-3-steps/

    See Step 1 for notes on CS pin init to help

  10. #10
    Senior Member
    Join Date
    Dec 2015
    Location
    LA
    Posts
    183
    Quote Originally Posted by Dionysus View Post
    So, I've wired Pin 9 to the T_CS pin on the touchscreen.... Do I need to initialize the touchscreen in order to make sure that it knows what its CS is? Or do I need to tell the flash chip that it should relinquish control when the touchscreen needs it?

    Same question about the audio shield and its SD card CS. I haven't actually told it to pay attention to pin 10. However, if sounds like you were able to get things to work with the audio shield + sd card and only that same code, so I guess that's not the answer.
    Sounds like a similar problem I had with a setup used for all sorts of SPI and I2C testing. I would leave everything connected even if I wasn't using it. After occasional issues, especially with Audio and SD card stuff, eventually figured out that each device connected should have the corresponding header files and startup code even if I wasn't using them.

    So you need tft.begin(), ts.begin(), sd.begin(), Serial.begin() ect. along with their declarations and any non standard pins. You should be able to get the required code from the individual programs you had working separately in other code. All pins with wires connected to the T4 need to be initialized in some fashion. I don't remember the T3.x being so sensitive to this but the T4 is.

  11. #11
    Member Dionysus's Avatar
    Join Date
    Apr 2020
    Location
    Chicago
    Posts
    32
    Holy cow, such a relief! To sum up for anyone coming here in the future, 1) triple check your soldering, 2) make sure that you also clean it up / re-flow, &c. and 3) also be sure to include the startup code for any potentially conflicting SPI devices. As it happens, I didn't need to include the code for the touchscreen, just including the startup code for the SD drive was enough. Obviously my final code will have it all, anyway.

    For a teensy 4.0 with a rev D audio shield and an ILI9341 touchscreen, here's the code that is currently working:

    Code:
    // RawHardwareTest - Check if a SPI Flash chip is compatible
    // with SerialFlash by performing many read and write tests
    // to its memory.
    //
    // The chip should be fully erased before running this test.
    // Use the EraseEverything to do a (slow) full chip erase.
    //
    // Normally you should NOT access the flash memory directly,
    // as this test program does.  You should create files and
    // read and write the files.  File creation allocates space
    // with program & erase boundaries within the chip, to allow
    // reading from any other files while a file is busy writing
    // or erasing (if created as erasable).
    //
    // If you discover an incompatible chip, please report it here:
    // https://github.com/PaulStoffregen/SerialFlash/issues
    // You MUST post the complete output of this program, and
    // the exact part number and manufacturer of the chip.
    
    
    #include <SerialFlash.h>
    #include <SPI.h>
    #include <SD.h>
    #define SDCARD_CS_PIN    10
    #define SDCARD_MOSI_PIN  11
    #define SDCARD_SCK_PIN   13
    const int SD_CS_Pin = 10;
    const int Display_CS_Pin = 14;
    const int Touch_CS_Pin = 8;
    const int FlashChipSelect = 6; // digital pin for flash chip CS pin
    //const int FlashChipSelect = 21; // Arduino 101 built-in SPI Flash
    
    SerialFlashFile file;
    
    const unsigned long testIncrement = 4096;
    
    void setup() {
      //uncomment these if using Teensy audio shield
      //SPI.setSCK(14);  // Audio shield has SCK on pin 14
      //SPI.setMOSI(7);  // Audio shield has MOSI on pin 7
    
      //uncomment these if you have other SPI chips connected
      //to keep them disabled while using only SerialFlash
      //pinMode(4, INPUT_PULLUP);
      //pinMode(10, INPUT_PULLUP);
    
      Serial.begin(9600);
    
      while (!Serial) ;
      delay(100);
    
      pinMode(SD_CS_Pin, OUTPUT);
      digitalWrite(SD_CS_Pin, HIGH);
      
      pinMode(Display_CS_Pin, OUTPUT);  
      digitalWrite(Display_CS_Pin, HIGH);
      
      pinMode(Touch_CS_Pin, OUTPUT);
      digitalWrite(Touch_CS_Pin, HIGH);
      
      delay(1);
    
      SPI.setMOSI(SDCARD_MOSI_PIN);
      SPI.setSCK(SDCARD_SCK_PIN);
      if (!(SD.begin(SDCARD_CS_PIN))) {
        while (1) {
          Serial.println("Unable to access the SD card");
          delay(500);
        }
      }
      delay(1000);
    
    
    
      Serial.println("Raw SerialFlash Hardware Test");
      SerialFlash.begin(FlashChipSelect); // proceed even if begin() fails
    
      if (test()) {
        Serial.println();
        Serial.println("All Tests Passed  :-)");
        Serial.println();
        Serial.println("Test data was written to your chip.  You must run");
        Serial.println("EraseEverything before using this chip for files.");
      } else {
        Serial.println();
        Serial.println("Tests Failed  :{");
        Serial.println();
        Serial.println("The flash chip may be left in an improper state.");
        Serial.println("You might need to power cycle to return to normal.");
      }
    }
    
    
    bool test() {
      unsigned char buf[256], sig[256], buf2[8];
      unsigned long address, count, chipsize, blocksize;
      unsigned long usec;
      bool first;
    
      // Read the chip identification
      Serial.println();
      Serial.println("Read Chip Identification:");
      SerialFlash.readID(buf);
      Serial.print("  JEDEC ID:     ");
      Serial.print(buf[0], HEX);
      Serial.print(" ");
      Serial.print(buf[1], HEX);
      Serial.print(" ");
      Serial.println(buf[2], HEX);
      Serial.print("  Part Nummber: ");
      Serial.println(id2chip(buf));
      Serial.print("  Memory Size:  ");
      chipsize = SerialFlash.capacity(buf);
      Serial.print(chipsize);
      Serial.println(" bytes");
      if (chipsize == 0) return false;
      Serial.print("  Block Size:   ");
      blocksize = SerialFlash.blockSize();
      Serial.print(blocksize);
      Serial.println(" bytes");
    
    
      // Read the entire chip.  Every test location must be
      // erased, or have a previously tested signature
      Serial.println();
      Serial.println("Reading Chip...");
      memset(buf, 0, sizeof(buf));
      memset(sig, 0, sizeof(sig));
      memset(buf2, 0, sizeof(buf2));
      address = 0;
      count = 0;
      first = true;
      while (address < chipsize) {
        SerialFlash.read(address, buf, 8);
        //Serial.print("  addr = ");
        //Serial.print(address, HEX);
        //Serial.print(", data = ");
        //printbuf(buf, 8);
        create_signature(address, sig);
        if (is_erased(buf, 8) == false) {
          if (equal_signatures(buf, sig) == false) {
            Serial.print("  Previous data found at address ");
            Serial.println(address);
            Serial.println("  You must fully erase the chip before this test");
            Serial.print("  found this: ");
            printbuf(buf, 8);
            Serial.print("     correct: ");
            printbuf(sig, 8);
            return false;
          }
        } else {
          count = count + 1; // number of blank signatures
        }
        if (first) {
          address = address + (testIncrement - 8);
          first = false;
        } else {
          address = address + 8;
          first = true;
        }
      }
    
    
      // Write any signatures that were blank on the original check
      if (count > 0) {
        Serial.println();
        Serial.print("Writing ");
        Serial.print(count);
        Serial.println(" signatures");
        memset(buf, 0, sizeof(buf));
        memset(sig, 0, sizeof(sig));
        memset(buf2, 0, sizeof(buf2));
        address = 0;
        first = true;
        while (address < chipsize) {
          SerialFlash.read(address, buf, 8);
          if (is_erased(buf, 8)) {
            create_signature(address, sig);
            //Serial.printf("write %08X: data: ", address);
            //printbuf(sig, 8);
            SerialFlash.write(address, sig, 8);
            while (!SerialFlash.ready()) ; // wait
            SerialFlash.read(address, buf, 8);
            if (equal_signatures(buf, sig) == false) {
              Serial.print("  error writing signature at ");
              Serial.println(address);
              Serial.print("  Read this: ");
              printbuf(buf, 8);
              Serial.print("  Expected:  ");
              printbuf(sig, 8);
              return false;
            }
          }
          if (first) {
            address = address + (testIncrement - 8);
            first = false;
          } else {
            address = address + 8;
            first = true;
          }
        }
      } else {
        Serial.println("  all signatures present from prior tests");
      }
    
    
      // Read all the signatures again, just to be sure
      // checks prior writing didn't corrupt any other data
      Serial.println();
      Serial.println("Double Checking All Signatures:");
      memset(buf, 0, sizeof(buf));
      memset(sig, 0, sizeof(sig));
      memset(buf2, 0, sizeof(buf2));
      count = 0;
      address = 0;
      first = true;
      while (address < chipsize) {
        SerialFlash.read(address, buf, 8);
        create_signature(address, sig);
        if (equal_signatures(buf, sig) == false) {
          Serial.print("  error in signature at ");
          Serial.println(address);
          Serial.print("  Read this: ");
          printbuf(buf, 8);
          Serial.print("  Expected:  ");
          printbuf(sig, 8);
          return false;
        }
        count = count + 1;
        if (first) {
          address = address + (testIncrement - 8);
          first = false;
        } else {
          address = address + 8;
          first = true;
        }
      }
      Serial.print("  all ");
      Serial.print(count);
      Serial.println(" signatures read ok");
    
    
      // Read pairs of adjacent signatures
      // check read works across boundaries
      Serial.println();
      Serial.println("Checking Signature Pairs");
      memset(buf, 0, sizeof(buf));
      memset(sig, 0, sizeof(sig));
      memset(buf2, 0, sizeof(buf2));
      count = 0;
      address = testIncrement - 8;
      first = true;
      while (address < chipsize - 8) {
        SerialFlash.read(address, buf, 16);
        create_signature(address, sig);
        create_signature(address + 8, sig + 8);
        if (memcmp(buf, sig, 16) != 0) {
          Serial.print("  error in signature pair at ");
          Serial.println(address);
          Serial.print("  Read this: ");
          printbuf(buf, 16);
          Serial.print("  Expected:  ");
          printbuf(sig, 16);
          return false;
        }
        count = count + 1;
        address = address + testIncrement;
      }
      Serial.print("  all ");
      Serial.print(count);
      Serial.println(" signature pairs read ok");
    
    
      // Write data and read while write in progress
      Serial.println();
      Serial.println("Checking Read-While-Write (Program Suspend)");
      address = 256;
      while (address < chipsize) { // find a blank space
        SerialFlash.read(address, buf, 256);
        if (is_erased(buf, 256)) break;
        address = address + 256;
      }
      if (address >= chipsize) {
        Serial.println("  error, unable to find any blank space!");
        return false;
      }
      for (int i=0; i < 256; i += 8) {
        create_signature(address + i, sig + i);
      }
      Serial.print("  write 256 bytes at ");
      Serial.println(address);
      Serial.flush();
      SerialFlash.write(address, sig, 256);
      usec = micros();
      if (SerialFlash.ready()) {
        Serial.println("  error, chip did not become busy after write");
        return false;
      }
      SerialFlash.read(0, buf2, 8); // read while busy writing
      while (!SerialFlash.ready()) ; // wait
      usec = micros() - usec;
      Serial.print("  write time was ");
      Serial.print(usec);
      Serial.println(" microseconds.");
      SerialFlash.read(address, buf, 256);
      if (memcmp(buf, sig, 256) != 0) {
        Serial.println("  error writing to flash");
        Serial.print("  Read this: ");
        printbuf(buf, 256);
        Serial.print("  Expected:  ");
        printbuf(sig, 256);
        return false;
      }
      create_signature(0, sig);
      if (memcmp(buf2, sig, 8) != 0) {
        Serial.println("  error, incorrect read while writing");
        Serial.print("  Read this: ");
        printbuf(buf2, 256);
        Serial.print("  Expected:  ");
        printbuf(sig, 256);
        return false;
      }
      Serial.print("  read-while-writing: ");
      printbuf(buf2, 8);
      Serial.println("  test passed, good read while writing");
    
    
    
      // Erase a block and read while erase in progress
      if (chipsize >= 262144 + blocksize + testIncrement) {
        Serial.println();
        Serial.println("Checking Read-While-Erase (Erase Suspend)");
        memset(buf, 0, sizeof(buf));
        memset(sig, 0, sizeof(sig));
        memset(buf2, 0, sizeof(buf2));
        SerialFlash.eraseBlock(262144);
        usec = micros();
        delayMicroseconds(50);
        if (SerialFlash.ready()) {
          Serial.println("  error, chip did not become busy after erase");
          return false;
        }
        SerialFlash.read(0, buf2, 8); // read while busy writing
        while (!SerialFlash.ready()) ; // wait
        usec = micros() - usec;
        Serial.print("  erase time was ");
        Serial.print(usec);
        Serial.println(" microseconds.");
        // read all signatures, check ones in this block got
        // erased, and all the others are still intact
        address = 0;
        first = true;
        while (address < chipsize) {
          SerialFlash.read(address, buf, 8);
          if (address >= 262144 && address < 262144 + blocksize) {
            if (is_erased(buf, 8) == false) {
              Serial.print("  error in erasing at ");
              Serial.println(address);
              Serial.print("  Read this: ");
              printbuf(buf, 8);
              return false;
            }
          } else {
            create_signature(address, sig);
            if (equal_signatures(buf, sig) == false) {
              Serial.print("  error in signature at ");
              Serial.println(address);
              Serial.print("  Read this: ");
              printbuf(buf, 8);
              Serial.print("  Expected:  ");
              printbuf(sig, 8);
              return false;
            }
          }
          if (first) {
            address = address + (testIncrement - 8);
            first = false;
          } else {
            address = address + 8;
            first = true;
          }
        }
        Serial.print("  erase correctly erased ");
        Serial.print(blocksize);
        Serial.println(" bytes");
        // now check if the data we read during erase is good
        create_signature(0, sig);
        if (memcmp(buf2, sig, 8) != 0) {
          Serial.println("  error, incorrect read while erasing");
          Serial.print("  Read this: ");
          printbuf(buf2, 256);
          Serial.print("  Expected:  ");
          printbuf(sig, 256);
          return false;
        }
        Serial.print("  read-while-erasing: ");
        printbuf(buf2, 8);
        Serial.println("  test passed, good read while erasing");
    
      } else {
        Serial.println("Skip Read-While-Erase, this chip is too small");
      }
    
    
    
    
      return true;
    }
    
    
    void loop() {
      // do nothing after the test
    }
    
    const char * id2chip(const unsigned char *id)
    {
    	if (id[0] == 0xEF) {
    		// Winbond
    		if (id[1] == 0x40) {
    			if (id[2] == 0x14) return "W25Q80BV";
    			if (id[2] == 0x15) return "W25Q16DV";
    			if (id[2] == 0x17) return "W25Q64FV";
    			if (id[2] == 0x18) return "W25Q128FV";
    			if (id[2] == 0x19) return "W25Q256FV";
    		}
    	}
    	if (id[0] == 0x01) {
    		// Spansion
    		if (id[1] == 0x02) {
    			if (id[2] == 0x16) return "S25FL064A";
    			if (id[2] == 0x19) return "S25FL256S";
    			if (id[2] == 0x20) return "S25FL512S";
    		}
    		if (id[1] == 0x20) {
    			if (id[2] == 0x18) return "S25FL127S";
    		}
    	}
    	if (id[0] == 0xC2) {
    		// Macronix
    		if (id[1] == 0x20) {
    			if (id[2] == 0x18) return "MX25L12805D";
    		}
    	}
    	if (id[0] == 0x20) {
    		// Micron
    		if (id[1] == 0xBA) {
    			if (id[2] == 0x20) return "N25Q512A";
    			if (id[2] == 0x21) return "N25Q00AA";
    		}
    		if (id[1] == 0xBB) {
    			if (id[2] == 0x22) return "MT25QL02GC";
    		}
    	}
    	if (id[0] == 0xBF) {
    		// SST
    		if (id[1] == 0x25) {
    			if (id[2] == 0x02) return "SST25WF010";
    			if (id[2] == 0x03) return "SST25WF020";
    			if (id[2] == 0x04) return "SST25WF040";
    			if (id[2] == 0x41) return "SST25VF016B";
    			if (id[2] == 0x4A) return "SST25VF032";
    		}
    		if (id[1] == 0x25) {
    			if (id[2] == 0x01) return "SST26VF016";
    			if (id[2] == 0x02) return "SST26VF032";
    			if (id[2] == 0x43) return "SST26VF064";
    		}
    	}
      	if (id[0] == 0x1F) {
        		// Adesto
       		if (id[1] == 0x89) {
          			if (id[2] == 0x01) return "AT25SF128A";
        		}  
      	} 	
    	return "(unknown chip)";
    }
    
    void print_signature(const unsigned char *data)
    {
    	Serial.print("data=");
    	for (unsigned char i=0; i < 8; i++) {
    		Serial.print(data[i]);
    		Serial.print(" ");
    	}
    	Serial.println();
    }
    
    void create_signature(unsigned long address, unsigned char *data)
    {
    	data[0] = address >> 24;
    	data[1] = address >> 16;
    	data[2] = address >> 8;
    	data[3] = address;
    	unsigned long hash = 2166136261ul;
    	for (unsigned char i=0; i < 4; i++) {
    		hash ^= data[i];
    		hash *= 16777619ul;
    	}
    	data[4] = hash;
    	data[5] = hash >> 8;
    	data[6] = hash >> 16;
    	data[7] = hash >> 24;
    }
    
    bool equal_signatures(const unsigned char *data1, const unsigned char *data2)
    {
    	for (unsigned char i=0; i < 8; i++) {
    		if (data1[i] != data2[i]) return false;
    	}
    	return true;
    }
    
    bool is_erased(const unsigned char *data, unsigned int len)
    {
    	while (len > 0) {
    		if (*data++ != 255) return false;
    		len = len - 1;
    	}
    	return true;
    }
    
    
    void printbuf(const void *buf, uint32_t len)
    {
      const uint8_t *p = (const uint8_t *)buf;
      do {
        unsigned char b = *p++;
        Serial.print(b >> 4, HEX);
        Serial.print(b & 15, HEX);
        //Serial.printf("%02X", *p++);
        Serial.print(" ");
      } while (--len > 0);
      Serial.println();
    }

    and here is the result:
    Code:
    Raw SerialFlash Hardware Test
    
    
    
    Read Chip Identification:
    
      JEDEC ID:     EF 40 18
    
      Part Nummber: W25Q128FV
    
      Memory Size:  16777216 bytes
    
      Block Size:   65536 bytes
    
    
    
    Reading Chip...
    
    
    
    Writing 8192 signatures
    
    
    
    Double Checking All Signatures:
    
      all 8192 signatures read ok
    
    
    
    Checking Signature Pairs
    
      all 4095 signature pairs read ok
    
    
    
    Checking Read-While-Write (Program Suspend)
    
      write 256 bytes at 256
    
      write time was 375 microseconds.
    
      read-while-writing: 00 00 00 00 15 F5 95 4B 
    
      test passed, good read while writing
    
    
    
    Checking Read-While-Erase (Erase Suspend)
    
      erase time was 155598 microseconds.
    
      erase correctly erased 65536 bytes
    
      read-while-erasing: 00 00 00 00 15 F5 95 4B 
    
      test passed, good read while erasing
    
    
    
    All Tests Passed  :-)
    
    
    
    Test data was written to your chip.  You must run
    
    EraseEverything before using this chip for files.


    Thank you again to everyone!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •