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

Thread: Is there a simple test for flash memory being soldered on the 4.1 correctly?

  1. #1
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,012

    Question Is there a simple test for flash memory being soldered on the 4.1 correctly?

    I have a Teensy 4.1 and it appears the PSRAM I soldered on to it either was mis-soldered or the chip does not work (external_psram_size is 0).

    I used Paul's test for psram:


    Is there a similar test for the flash memory chip? Before I get to un-soldering and re-soldering the chips, I would like to know if the flash memory at least works or if I need to replace both chips.

    I recall having old programs in the past that verified flash and psram. These were written before the flash/psram was integrated into the Arduino code. So, I was wondering if there is newer code.

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,863
    Sorry to hear you are having some issues... One thing I have done when I see things like this is to run the pin test that @defragster and myself played with...
    Code:
    void setup() {
      Serial.begin(115200);
      while (!Serial && millis() < 4000 );
      Serial.println("Compile Time:: " __FILE__ " " __DATE__ " " __TIME__);
      Serial.printf("Num Digital Pins: %d\n", NUM_DIGITAL_PINS);
    
      testForShorts();
      
    }
    
    uint32_t cnt = 0;
    void loop() {
      cnt++;
        allPinTest( cnt );
    }
    
    uint32_t pinLast[NUM_DIGITAL_PINS];
    void allPinTest( uint32_t cnt ) {
      uint32_t ii, SET;
      Serial.print("PULLDOWN Start Vals:\n  ");
      SET = 0;
      Serial.print("PULLDOWN :: TEST to 3.3V\n  ");
      for ( ii = 0; ii < NUM_DIGITAL_PINS; ii++) {
        pinMode( ii, INPUT_PULLDOWN );
        delayMicroseconds( 5 );
        pinLast[ii] = digitalReadFast( ii );
        if (pinLast[ii]) {
          Serial.print("\nd#=");
          Serial.print( ii );
          Serial.print( " val=" );
        }
        Serial.print( pinLast[ii] );
        Serial.print(',');
      }
      Serial.println();
      Serial.println();
      while ( 1 ) {
        uint32_t jj, dd = 0, cc = 0, ee=4;
        cc = 0;
        for ( ii = 0; ii < NUM_DIGITAL_PINS; ii++) {
          jj = digitalReadFast( ii );
          if ( jj != pinLast[ii] ) {
            dd = 1;
            cc++;
            pinLast[ii] = jj;
            Serial.print("d#=");
            Serial.print( ii );
            if ( pinLast[ii] ) Serial.print( "\t" );
            Serial.print( " val=" );
            Serial.print( pinLast[ii] );
            Serial.print(',');
          }
          if ( cc > 1 && ee ) {
            Serial.println(">>> MULTI CHANGE !!");
            ee--;
          }
          if ( Serial.available() ) {
            while ( Serial.available() ) Serial.read();
            if ( 0 == SET ) {
              SET = 1;
              Serial.print("PULLUP :: TEST TO GND\n  ");
            }
            else {
              SET = 0;
              Serial.print("PULLDOWN :: TEST to 3.3V\n  ");
            }
            for ( ii = 0; ii < NUM_DIGITAL_PINS; ii++) {
              if ( 0 == SET )
                pinMode( ii, INPUT_PULLDOWN );
              else
                pinMode( ii, INPUT_PULLUP );
              delayMicroseconds( 20 );
              pinLast[ii] = digitalReadFast( ii );
              if (SET != pinLast[ii]) {
                Serial.print("d#=");
                Serial.print( ii );
                Serial.print( " val=" );
                Serial.println( pinLast[ii] );
              }
            }
          }
        }
        if ( dd ) {
          dd = 0;
          Serial.println();
          delay( 50 );
        }
      }
    }
    
    void testForShorts() {
      uint32_t ii;
      Serial.print("Quick Test for Shorts to adjacent pin");
      Serial.println("First pull pins down and see if the next one follows");
      for ( ii = 0; ii < NUM_DIGITAL_PINS-1; ii++) {
        pinMode( ii+1, INPUT_PULLDOWN );
        pinMode( ii, OUTPUT);
        digitalWrite(ii, HIGH);
        delayMicroseconds( 5 );
        if (digitalRead(ii+1)) {
          Serial.printf("%d:%d ", ii, ii+1);
        }
      }
      Serial.println("\n Now try Pull up and see if setting low follow");
      for ( ii = 0; ii < NUM_DIGITAL_PINS-1; ii++) {
        pinMode( ii+1, INPUT_PULLUP );
        pinMode( ii, OUTPUT);
        digitalWrite(ii, LOW);
        delayMicroseconds( 5 );
        if (!digitalRead(ii+1)) {
          Serial.printf("%d:%d ", ii, ii+1);
        }
      }
      Serial.println();  
    }
    You can alternate between using a jumper wire from GND or 3.3v and when you touch a pin in the right mode (first test is from 3.3v to it the second test is from GND to pin) and when you touch a pin it should tell you which pin you touched.

    And if there is a short between pins you may see a message like multiple pins changed state, which is a good clue.

    Also at startup it tries a quick and dirty test looking for shorts, of setting all IO pins to INPUT_PULLDOWN, and one by one it sets a pin to OUTPUT and HIGH and checks for the next pin up to see if it changed state as well...

    If it looks like that works, I might try something like the LFSIntegerity example sketch in the LittleFS library examples, to see if it looks like that might work. You would probably need to set the type of chip you are looking to test. Like TEST_QSPI.

  3. #3
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,763
    I sometimes have the same problem with soldering.

    Besides what @KurtE posted I typically run the following sketch which tests the Flash using LittleFS. If it works no problem then I move on to debugging or I will usually just touch up the pins with solder (I miss sometimes):
    Code:
    #include <LittleFS.h>
    uint64_t fTot, totSize1;
    
    
    LittleFS_QSPIFlash myfs;
    //LittleFS_Program myfs;
    //LittleFS_SPIFlash myfs;
    
    #define chipSelect 3
    
    File file, file1, file3;
    
    
    #include <ctime>
    
    
    void setup() {
      //pinMode(13, OUTPUT);
      pinMode(chipSelect, OUTPUT);
      digitalWrite(chipSelect, HIGH);
      while (!Serial) ; // wait
    
      delay(1000);
      Serial.println("LittleFS Test"); delay(5);
      if (!myfs.begin()) {
      //if (!myfs.begin(chipSelect)) {
        Serial.println("Error starting spidisk");
        while (1) ;
      }
    
    
      Serial.printf("TotalSize (Bytes): %d\n", myfs.totalSize());
      //myfs.deviceErase();
    
      delay(1000);
      Serial.println("started");
      //printDirectory();
      delay(10);
      Serial.println("MAKE files");
      myfs.mkdir("structureData1");
      printDirectory();
      file = myfs.open("structureData1/temp_test.txt", FILE_WRITE);
      delay(10);
      file.println("SOME DATA TO TEST");
      file.close();
      file = myfs.open("temp_test1.txt", FILE_WRITE);
      delay(10);
      file.println("SOME DATA TO TEST");
      file.close();
      file = myfs.open("temp_test2.txt", FILE_WRITE);
      delay(10);
      file.println("SOME DATA TO TEST");
      file.close();
    
      uint8_t buffer[] = "Test for SOME DATA TO TEST";
      Serial.println("--------------");
      file = myfs.open("temp_test3.txt", FILE_WRITE);
      uint16_t writeSize = sizeof(buffer);
      uint16_t write2Buffer = 512 / writeSize;
    
      uint8_t tempBuffer[512];
      memset(tempBuffer, 0xFF, 512);
      for (uint16_t j = 0; j < write2Buffer; j++) {
        for (uint16_t i = 0; i < writeSize; i++) {
          tempBuffer[j * writeSize + i] = buffer[i];
        }
      }
      for (uint16_t j = 0; j < 2; j++)
        file.write(tempBuffer, sizeof(tempBuffer));
      delay(10);
    
      file.close();
    
      delay(100);
      printDirectory();
      delay(10);
    
      Serial.printf("Disk Usuage:\n");
      Serial.printf("Bytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
    
      uint8_t buf[2048];
      memset(buf, 0, 2048);
      file = myfs.open("temp_test3.txt", FILE_READ);
      file.read(buf, 2048);
      for (uint16_t i = 0; i < 15; i++) {
        for (uint16_t j = 0; j < sizeof(buffer); j++) {
          Serial.printf("%c", buf[j + sizeof(buffer)*i]);
        } Serial.println();
      }
      file.close();
      
    
    }
    
    void bigFile() {
      char someData[2048];
      memset( someData, 'z', 2048 );
      file = myfs.open("bigfile.txt  ", FILE_WRITE);
      file.write(someData, sizeof(someData));
    
      for (uint16_t j = 0; j < 300; j++)
        file.write(someData, sizeof(someData));
      file.close();
      printDirectory();
    }
    
    void loop() {
      if ( Serial.available() ) {
        char rr;
        rr = Serial.read();
        if (rr == 'B') bigFile2MB(1);
        if (rr == 'b') bigFile2MB(0);
        if (rr == 'q') myfs.quickFormat();
        if (rr == 'F') myfs.lowLevelFormat('.');
        if (rr == 'f') myfs.formatUnused( 0 , 0 );
    
        printDirectory();
      time_t t = rtc_get();
      Serial.print(std::ctime(&t));
      }
    }
    
    void printDirectory() {
    
      Serial.println("printDirectory\n--------------");
      printDirectory(myfs.open("/"), 0);
      Serial.println();
    }
    
    
    void printDirectory(File dir, int numTabs) {
      //dir.whoami();
      uint64_t fSize = 0;
      uint32_t dCnt = 0, fCnt = 0;
      if ( 0 == dir ) {
        Serial.printf( "\t>>>\t>>>>> No Dir\n" );
        return;
      }
      while (true) {
        File entry =  dir.openNextFile();
        if (! entry) {
          // no more files
          Serial.printf("\n %u dirs with %u files of Size %u Bytes\n", dCnt, fCnt, fSize);
          fTot += fCnt;
          totSize1 += fSize;
          break;
        }
        for (uint8_t i = 0; i < numTabs; i++) {
          Serial.print('\t');
        }
    
        if (entry.isDirectory()) {
          Serial.print("DIR\t");
          dCnt++;
        } else {
          Serial.print("FILE\t");
          fCnt++;
          fSize += entry.size();
        }
        Serial.print(entry.name());
        if (entry.isDirectory()) {
          Serial.println(" / ");
          printDirectory(entry, numTabs + 1);
        } else {
          // files have sizes, directories do not
          Serial.print("\t\t");
          Serial.println(entry.size(), DEC);
        }
        entry.close();
        //Serial.flush();
      }
    }
    
    void bigFile2MB( int doThis ) {
      char myFile[] = "/0_2MBfile.txt";
      char fileID = '0' - 1;
    
      if ( 0 == doThis ) {  // delete File
        Serial.printf( "\nDelete with read verify all #bigfile's\n");
        do {
          fileID++;
          myFile[1] = fileID;
          if ( myfs.exists(myFile) && bigVerify( myFile, fileID) ) {
            //filecount--;
            myfs.remove(myFile);
          }
          else break; // no more of these
        } while ( 1 );
      }
      else {  // FILL DISK
        lfs_ssize_t resW = 1;
        char someData[2048];
        uint32_t xx, toWrite;
        toWrite = 2048 * 1000;
        if ( toWrite > (65535 + (myfs.totalSize() - myfs.usedSize()) ) ) {
          Serial.print( "Disk too full! DO :: q or F");
          return;
        }
        xx = toWrite;
        Serial.printf( "\nStart Big write of %u Bytes", xx);
        uint32_t timeMe = micros();
        file3 = nullptr;
        do {
          if ( file3 ) file3.close();
          fileID++;
          myFile[1] = fileID;
          file3 = myfs.open(myFile, FILE_WRITE);
        } while ( fileID < '9' && file3.size() > 0);
        if ( fileID == '9' ) {
          Serial.print( "Disk has 9 FILES 0-8! DO :: b or q or F");
          return;
        }
        memset( someData, fileID, 2048 );
        int hh = 0;
        while ( toWrite >= 2048 && resW > 0 ) {
          resW = file3.write( someData , 2048 );
          hh++;
          if ( !(hh % 40) ) Serial.print('.');
          toWrite -= 2048;
        }
        xx -= toWrite;
        file3.close();
        timeMe = micros() - timeMe;
        file3 = myfs.open(myFile, FILE_WRITE);
        if ( file3.size() > 0 ) {
          //filecount++;
          Serial.printf( "\nBig write %s took %5.2f Sec for %lu Bytes : file3.size()=%llu", myFile , timeMe / 1000000.0, xx, file3.size() );
        }
        if ( file3 != 0 ) file3.close();
        Serial.printf( "\n\tBig write KBytes per second %5.2f \n", xx / (timeMe / 1000.0) );
        Serial.printf("\nBytes Used: %llu, Bytes Total:%llu\n", myfs.usedSize(), myfs.totalSize());
        if ( resW < 0 ) {
          Serial.printf( "\nBig write ERR# %i 0x%X \n", resW, resW );
          //errsLFS++;
          myfs.remove(myFile);
        }
      }
    }
    
    bool bigVerify( char szPath[], char chNow ) {
      uint32_t timeMe = micros();
      file3 = myfs.open(szPath);
      if ( 0 == file3 ) {
        return false;
      }
      char mm;
      uint32_t ii = 0;
      uint32_t kk = file3.size() / 50;
      Serial.printf( "\tVerify %s bytes %llu : ", szPath, file3.size() );
      while ( file3.available() ) {
        file3.read( &mm , 1 );
        //rdCnt++;
        ii++;
        if ( !(ii % kk) ) Serial.print('.');
        if ( chNow != mm ) {
          Serial.printf( "<Bad Byte!  %c! = %c [0x%X] @%u\n", chNow, mm, mm, ii );
          //parseCmd( '0' );
          //errsLFS++;
          //checkInput( 1 );
          break;
        }
      }
      if (ii != file3.size()) {
        Serial.printf( "\n\tRead Count fail! :: read %u != f.size %llu\n", ii, file3.size() );
        //parseCmd( '0' );
        //errsLFS++;
        //checkInput( 1 );  // PAUSE on CmdLine
      }
      else
        Serial.printf( "\tGOOD! >>  bytes %lu", ii );
      file3.close();
      timeMe = micros() - timeMe;
      Serial.printf( "\n\tBig read&compare KBytes per second %5.2f \n", ii / (timeMe / 1000.0) );
      if ( 0 == ii ) return false;
      return true;
    }

  4. #4
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,012
    Hmmm, mjs513:

    Code:
    Teensy41_flash: In function 'void loop()':
    Teensy41_flash:117: error: 'class LittleFS_QSPIFlash' has no member named 'formatUnused'
         if (rr == 'f') myfs.formatUnused( 0 , 0 );
                             ^
    'class LittleFS_QSPIFlash' has no member named 'formatUnused'
    If I delete the line that references it, it seems to work:

    Code:
        if (rr == 'f') myfs.formatUnused( 0 , 0 );
    Thanks. That means just the psram looks bad.

  5. #5
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,012
    And it looks like it is pins 52 and 54 that need to be soldered on the psram. Thanks, KurtE.

    Before getting to the soldering however, I was reattaching the Teensy to the RGB display I had it running, forgetting I was running pintest. There was a little smoke as I probably touched the wrong pin, but I disconnected things before things became completely damaged. FWIW, the RGB display is running fine and the flash test also ran fine after I brought things back up.

    Note, in running pintest, I had a micro SD card in the micro SD card reader, and it said that pins 46 and 47 might be shorted. When I took out the SD card, it was fine.
    Last edited by MichaelMeissner; 02-04-2021 at 01:26 AM.

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    13,724
    @MM - myfs.formatUnused( 0 , 0 ); - is post bet 5 'aftermarket' code I added to pre-format unused media blocks so they can be made ready for write at full speed later without needing to FORMAT before use as those blocks come into play after they have been used and recorded as unused by LittleFS.

    Hoping it seems useful for inclusion in Beta 6.

    Hope the smoke you saw wasn't the magic kind ...

    Did you reflow the solder on the PSRAM with some flux (paste or liquid) then clean and dry?

    The PJRC PSRAM test is a nice simple self contained test - would be nice to have one for FLASH - but they don't have the setup done on startup - and there is not a single chip to accept and work with. With updates in Beta 6 of TD 1.54 it could be better with LittleFS though.

  7. #7
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    4,012
    Yes, in terms of the smoke, evidently I didn't release enough of it, as it seems to work.

    I used my soldering iron at the highest heat and solder braid to remove the solder from all 4 pins on the one side (3.3v, pins 54-52), leaving the other side still attached, and then 1-by-1, redid the solder. Yeah, I know I should solder chips like that by laying down solder first and then putting the chip on top of the solder and heating it, but I tend to do by having the chip directly on the pads, and then running a bit of solder on top of the pin. When I initially did the solder, I tested it my normal method of a LED/resistor and having a program that asked for a pin #, and then turned on that pin. Unfortunately, I think I tested by putting the power wire from the LED on the pad itself, and not on the metal on the chip.

    It would be nice if both programs got added to the examples in 1.54 beta 6 (pintest also for that matter).

  8. #8
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,763
    @MichaelMeissner - Sorry about that. As @defragster stated "myfs.formatUnused( 0 , 0 );" was an addition that was added as we were updating LittleFS. I forgot to remove it from code I posted. Right now that change as well as the addition of that example was added in the PR to LittleFS (https://github.com/PaulStoffregen/LittleFS/pull/7) when we added in the changes necessary to support FRAM, FeRAM and NAND chips.

  9. #9
    Junior Member
    Join Date
    Mar 2021
    Location
    Eastern U.S.A.
    Posts
    4
    After discovering this thread when wanting to verify that my flash chip is in working order after soldering it and the PSRAM to my Teensy 4.1 board, I have ran into a problem. I have poked and looked around for a solution before posting, but now I am totally stuck. I already used "teensy41_psram_memtest.ino" to verify my PSRAM and it checks out, but when running the provided code from @mjs513 to check the flash, it gives me the following error compiling:

    Arduino: 1.8.13 (Windows 10), TD: 1.53, Board: "Teensy 4.1, Serial, 600 MHz, Faster, US English"
    In file included from C:\Users\me\Arduino IDE\portable\sketchbook\TEST_FLASH_VIA_LittleFS\TE ST_FLASH_VIA_LittleFS.ino:1:0:
    C:\Users\me\Arduino IDE\portable\sketchbook\libraries\LittleFS-main\src/LittleFS.h:25:16: fatal error: FS.h: No such file or directory
    compilation terminated.
    Error compiling for board Teensy 4.1.

    I did some poking around, and the "FS.h" file doesn't exist in the Teensy4 core:
    C:\Users\me\Arduino IDE\hardware\teensy\avr\cores\teensy4

    I did find it in the Teensy3 core:
    C:\Users\me\Arduino IDE\hardware\teensy\avr\cores\teensy3

    I copied the code provided by @mjs513 exactly, commenting out the "myfs.formatUnused( 0 , 0 );" line. I would repost it, but it seems redundant to do so. Anyone have any ideas as to what I may be missing here? Thanks!

  10. #10
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    6,763
    @howie.S - you didn't say which version of Teensyduino you are using. Suggest you download and install the beta7 version: https://forum.pjrc.com/threads/66357...l=1#post271199

  11. #11
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    8,863
    It should be in both Teensy3 and Teensy4 branches. And they are identical up on github, so you should be able to simply copy the one from the Teensy3 directory to the Teensy4 directory...

    Or install the latest beta releases of Teensyduino.

  12. #12
    Junior Member
    Join Date
    Mar 2021
    Location
    Eastern U.S.A.
    Posts
    4
    @mjs513, I apologize, it totally slipped my mind to provide the version of Teensyduino. The version I have is 1.53 (current, non-beta). Thank you both for helping @@mjs513 @KurtE. You guys are *super* fast, replies came before breakfast and shower was over lol. I think I will take both of your advice and install the beta release and see if it corrects the issue. Although I wonder why the "FS.h" file is missing from the Teensy4 core, and not the Teensy3 core? I used the installer to install Teensyduino into my Arduino IDE as usual. I will post the results shortly. Thanks again!

  13. #13
    Junior Member
    Join Date
    Mar 2021
    Location
    Eastern U.S.A.
    Posts
    4
    After taking the advice to upgrade to the beta7 version the code compiles as fine as powder. Big thanks @@mjs513 @KurtE for the extremely fast reply and the advice, you guys are awesome.

  14. #14
    Junior Member
    Join Date
    Mar 2021
    Location
    Eastern U.S.A.
    Posts
    4
    Looking back, I did provide my version of Teensyduino lol Look -->> Arduino: 1.8.13 (Windows 10), TD: 1.53, Board: "Teensy 4.1, Serial, 600 MHz, Faster, US English"
    The Arduino IDE spits out Teensyduino version when outputting info from the compiler. The included " TD: 1.53 " part of that string includes Teensy version. Neat. Thanks again guys.

  15. #15
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,974
    Quote Originally Posted by Howie.S View Post
    Although I wonder why the "FS.h" file is missing from the Teensy4 core, and not the Teensy3 core?
    That file exists because I've been planning to add this to Teensy's core library for a very long time. But the FS.h in 1.53's teensy3 folder isn't functional. It's more of a placeholder or experiment than actual usable code. In 1.53, nothing uses or even includes it. In hindsight, I probably shouldn't have put it into the publicly published code.

Posting Permissions

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