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

Thread: Serial Flash file.erase() not working?

  1. #1
    Junior Member
    Join Date
    Nov 2020
    Location
    Kyiv, Ukraine
    Posts
    6

    Serial Flash file.erase() not working?

    Hi, I ran into a problem while building an audio looper.
    When I call file.erase() it actually blocks the code for a while, but when I call SerialFlash.exists() after, it still returns "true". If you remove the file with remove() after erase(), the exists() returns false. However, in both cases the file is not actually erased, and the chip eventually runs out of memory. I've put together a code that shows this issue. After running "eraseTest()" a number of timer (in my case with 8Mb chip - 11 tries) it's no longer able to create a new file, not until you run full chip erase.

    Board: Teensy 3.6
    Audio adapter with Winbond 25Q64FVSIG soldered onto the Audio board.
    Arduino IDE 1.8.13
    Teensyduino version 1.53
    Windows 10

    It seems that a friend of mine reproduced it with Teensy 4.0 and a breakout with SPI flash.

    Here's the code that reproduces the problem:
    Code:
    #include <SPI.h>
    #include <SerialFlash.h>
    
    #define FLASH_CHIP_SELECT  6
    
    // The file where data is recorded
    SerialFlashFile file0;
    SerialFlashFile file1;
    SerialFlashFile file2;
    
    
    //define file size
    float filesize = 65536 * 10;
    
    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
    
      Serial.begin(115200);
    
      // Start SerialFlash
      if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1) {
          Serial.println ("Cannot access SPI Flash chip");
          delay (1000);
        }
      }
      Serial.println("READY TO GO");
    
    }
    void eraseTest() {
      const char *filename = "test.csv";
      byte buffer[512];
      static int n = 0;
      for (int i = 0; i < 512; i++) {
        buffer[i] = i % 10 + n;
      }
    
      Serial.print("Creating file...");
      Serial.println(filename);
      if (!SerialFlash.exists(filename)) {
        SerialFlash.createErasable(filename, filesize);
      }
      else Serial.println(" file already exists");
    
      file0 = SerialFlash.open(filename);
      if (file0) {
        file0.write(buffer, 512);
      }
      else {
        Serial.println("unable to create file");
        return;
      }
      file0.close();
      
      delay(10);
    
      Serial.println("Read test:");
      byte buf[256];
      file1 = SerialFlash.open(filename);
      file1.read(buf,256);
      for (int i = 42; i < 58; i++) {
        Serial.print(buf[i]); Serial.print(",");
      }
      Serial.println();
    
      delay(10);
      Serial.println("Erasing file...");
      unsigned long t = millis();
      file2 = SerialFlash.open(filename);
      file2.erase();
      Serial.print("done in ");
      Serial.print(millis()-t);
      Serial.println(" ms");
      delay(10);
      Serial.print("Checking if file exists:"); 
      Serial.println(SerialFlash.exists(filename));
      Serial.println("removing with remove() ");
      SerialFlash.remove(filename);
      Serial.print("Checking if file exists again:"); 
      Serial.println(SerialFlash.exists(filename));
      
      Serial.print("counter:"); Serial.println(n++);
    }
    
    void loop() {
      eraseTest();
      delay(1000);
    }
    Could anybody try running this? Any help would be much appreciated.

  2. #2
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,989
    Lets take a look at the documentation:
    For remove, it states:
    Delete A File

    SerialFlash.remove(filename);
    The actual space used by the file is not reclaimed. However, a new file with this name may be created after the original is deleted.
    So remove does not not free any space. It just meas you can create a new file with the same name.
    Deleting the filename would need time-expensive operations. Clearing a flash-block and rewriting it takes a long time.
    So, I'm not 100% sure and it would be necessary to take a look at the source code, but I would say it's pretty normal for exists() to still report the existence of the file.

    rase Data

    file.erase();
    Only files created for erasing can be erased. The entire file is erased to all 255 (0xFF) bytes, which allows the file to be written with new data.

    The contents of the file are erased. Not filename.
    Again, I'd say it's pretty normal that exists() still reports the existing of the file.

    I may be wrong or misunderstood something, but I can't see a bug here.
    It's just that your expectations differ from the documentation.

    Edit: doing both erase() and remove(), as in your program, does not help.

    Not sure what the Audio-Looper does - For live-recording which involves over-writing, a Flash-chip is wrong type of memory....
    Maybe use a SD-Card? It handles the erasing in the background and assignes empty blocks for new data automatically. The controller on the card does this.
    Last edited by Frank B; 02-15-2021 at 12:14 PM.

  3. #3
    Junior Member
    Join Date
    Nov 2020
    Location
    Kyiv, Ukraine
    Posts
    6
    Thanks Frank, I did investigate this and even looked inside the library. As you can see the problem is although I use erase(), the chip still runs out of space after a certain predictable amount of created files. So the erase in this case, although seems to be going over the blocks for a while, does not actually free up the space on the flash chip as the docs suggest.

    As for SD, it was used in earlier stage, however the SD libraries that I tried do not support simultaneous read and write that are so crucial for my looper setup. Hence the switch to the flash memory.

    If you happen to have the hardware to try and reproduce it, it would be much appreciated.

  4. #4
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,989
    I can test it - maybe we find a so far unknown bug?
    But I'll remove the remove()

  5. #5
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,989
    Quote Originally Posted by Frank B View Post
    I can test it - maybe we find a so far unknown bug?
    But I'll remove the remove()
    The counter is at 202 now. How long does it take?

    I'm using this:
    Code:
    #include <SPI.h>
    #include <SerialFlash.h>
    
    #define FLASH_CHIP_SELECT  6
    
    // The file where data is recorded
    SerialFlashFile file0;
    SerialFlashFile file1;
    SerialFlashFile file2;
    
    
    //define file size
    float filesize = 65536 * 10;
    
    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
    
      Serial.begin(115200);
    
      // Start SerialFlash
      if (!SerialFlash.begin(FLASH_CHIP_SELECT)) {
        while (1) {
          Serial.println ("Cannot access SPI Flash chip");
          delay (1000);
        }
      }
      Serial.println("READY TO GO");
    
    }
    void eraseTest() {
      const char *filename = "test.csv";
      byte buffer[512];
      static int n = 0;
      for (int i = 0; i < 512; i++) {
        buffer[i] = i % 10 + n;
      }
    
      Serial.print("Creating file...");
      Serial.println(filename);
      if (!SerialFlash.exists(filename)) {
        SerialFlash.createErasable(filename, filesize);
      }
      else Serial.println(" file already exists");
    
      file0 = SerialFlash.open(filename);
      if (file0) {
        file0.write(buffer, 512);
      }
      else {
        Serial.println("unable to create file");
        return;
      }
      file0.close();
      
      delay(10);
    
      Serial.println("Read test:");
      byte buf[256];
      file1 = SerialFlash.open(filename);
      file1.read(buf,256);
      for (int i = 42; i < 58; i++) {
        Serial.print(buf[i]); Serial.print(",");
      }
      Serial.println();
    
      delay(10);
      Serial.println("Erasing file...");
      unsigned long t = millis();
      file2 = SerialFlash.open(filename);
      file2.erase();
      Serial.print("done in ");
      Serial.print(millis()-t);
      Serial.println(" ms");
    #if 0  
      delay(10);
      Serial.print("Checking if file exists:"); 
      Serial.println(SerialFlash.exists(filename));
      Serial.println("removing with remove() ");
      SerialFlash.remove(filename);
      Serial.print("Checking if file exists again:"); 
      Serial.println(SerialFlash.exists(filename));
    #endif
      Serial.print("counter:"); Serial.println(n++);
    }
    
    void loop() {
      eraseTest();
      delay(1000);
    }
    Edit: 258

  6. #6
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,989
    I'm stopping the test now.
    Code:
    Read test:
    114,115,116,117,118,119,120,121,112,113,114,115,116,117,118,119,
    Erasing file...
    done in 1306 ms
    counter:624
    Creating file...test.csv
     file already exists
    Read test:
    115,116,117,118,119,120,121,122,113,114,115,116,117,118,119,120,
    Erasing file...
    done in 1272 ms
    It works without problems (with remove() removed)

  7. #7
    Junior Member
    Join Date
    Nov 2020
    Location
    Kyiv, Ukraine
    Posts
    6
    Hi Frank, thanks a lot for giving it some time. Can I ask you, what kind of memory chip you're using? Your erase time is much faster than mine (mine is ~2000ms).

    Seems that I misunderstood the function of file.erase() after all, and file.remove() indeed "cancels out" with the erase. And instead of checking for existence of the file, I should just make sure somehow it was erased and then just write to it. Thanks a lot!

  8. #8
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    7,989
    Good question. It was illegible, so I had to take a picture and enlarge it. It is a very old audio shield.
    It looks like I soldered in a W25Q128FV*.

    For this test I connected the audio board to a Teensy 3.2.

    You can test the file is empty by reading it. if it returns all 0xff it's empty.
    But, this is not needed. You can just erase() without checking.

    Glad that it works now.

    *I can't read the other markings. After "FV" comes a 8 or"B"? , maybe. (Edit: No, "S")
    The second line is completely unreadable. Would be interesting to know the year of production!
    Last edited by Frank B; 02-16-2021 at 01:26 PM.

Posting Permissions

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