Skip to content

BUG? ESP32 FFAT partition not hold second file(with format false!) #3609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
PC-maniak opened this issue Jan 2, 2020 · 15 comments · Fixed by #3611
Closed

BUG? ESP32 FFAT partition not hold second file(with format false!) #3609

PC-maniak opened this issue Jan 2, 2020 · 15 comments · Fixed by #3611

Comments

@PC-maniak
Copy link

PC-maniak commented Jan 2, 2020

Hardware:

Board: ESP32-WROOM-32U IPEX 16MB flash
Core Installation/update date: ?arduino->boards manager -> install esp 1.0.4
IDE name: Arduino IDE
Flash Frequency: 40Mhz
PSRAM enabled: no
Upload Speed: 115200
Computer OS: Windows 10 ,Ubuntu

Description:

hi i was excited about speed ffat against spiffs it's really fast but in tests i found a problem when writing from code more file than just one and reset the board so it is readable only the first file the next one .. i see their names but the content is nothing

TEST Windows :
//Read the flash file system (previously formatted) and copy as local disc image
esptool.py --chip esp32 --port COM3 --baud 921600 read_flash 0x300000 0x100000 fatfs.img

OSF mount fatfs.img as disk(read the file same as arduino code .. the first file is OK and the others have 0 bytes in size)

-> write NEW file to mounted disk

//Write a disc image
esptool.py --chip esp32 --port COM3 --baud 921600 --before esp32r0 --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x300000 fatfs.img

result : same .. empty file (some files contain garbage)

sketch : example -> FFAT_TEST (FORMAT : first format FFAT and then change to false)

writeFile(FFat, "/First.txt", "Hello First");
writeFile(FFat, "/Second.txt", "Hello Second"); //after reset board this is empty file

Debug Messages:

Enable Core debug level: Debug on tools menu of Arduino IDE, then put the serial output here 
@lbernstone
Copy link
Contributor

Unable to reproduce. This has been tested and used by many people. You cannot work directly on the file system outside of the device, as it uses the wear_levelling library. See https://github.com/marcmerlin/esp32_fatfsimage for a utility to create a disk image.

@PC-maniak
Copy link
Author

Hi :) but this should work? why it doesn't work .. (it works on spiffs)
writeFile(FFat, "/First.txt", "Hello First");
writeFile(FFat, "/Second.txt", "Hello Second"); //after reset board this is empty file

@lbernstone
Copy link
Contributor

You have damaged the file system. If you wipe the flash, and run the test without ever modifying ffat outside of the device, it works correctly.

@PC-maniak
Copy link
Author

you don't understand me .. without any work outside the system .. first load sketch which formats fat and writes those two files .. then load sketch which does not format FAT and reads those files .. file 1 works .. other file is empty

@lbernstone
Copy link
Contributor

Works for me

@PC-maniak
Copy link
Author

hm maybe I have a board with a damaged flash .. I'll try another tomorrow (in the workshop I have one more) and write the result ... it's weird :-/

@lbernstone
Copy link
Contributor

Erase your flash and try again.

@PC-maniak
Copy link
Author

I tried erase flash as the first option :)

@lbernstone
Copy link
Contributor

This code works fine for me. If I had written the example, I would have put file.close() in the functions just for good hygiene.

#include "FFat.h"

void readFile(fs::FS &fs, const char * path){
    Serial.printf("Reading file: %s\r\n", path);
    File file = fs.open(path);
    if(!file || file.isDirectory()){
        Serial.println("- failed to open file for reading");
        return;
    }
    Serial.println("- read from file:");
    while(file.available()){
        Serial.write(file.read());
    }
}

void writeFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Writing file: %s\r\n", path);
    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("- failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("- file written");
    } else {
        Serial.println("- write failed");
    }
}

void setup(){
    Serial.begin(115200);
    FFat.begin(true);
    readFile(FFat, "/second.txt");
    writeFile(FFat, "/hello.txt", "Hello ");
    writeFile(FFat, "/second.txt", "second\n");
}

void loop(){}

@PC-maniak
Copy link
Author

PC-maniak commented Jan 3, 2020

Hi =) on the second, the first file does not work either .. the first is not zero .. but reading the file is empty ...

Listing directory: /
FILE: /hello.txt SIZE: 6
FILE: /second.txt SIZE: 0
Reading file: /hello.txt

  • read from file:
    Hello Reading file: /second.txt
  • read from file:

I close .. i will continue to use spiffs .. on fat i can not rely when it makes me such a problem

@lbernstone
Copy link
Contributor

Please don't close the issue if you think there is still a bug.
I have provided exact code which works correctly on my hardware. You have not provided code that I can test to reproduce the issue.

@PC-maniak PC-maniak reopened this Jan 4, 2020
@PC-maniak
Copy link
Author

`FORMAT - WRITE :


#include "FFat.h"

// You only need to format FFat the first time you run a test
#define FORMAT_FFAT true

void writeFile(fs::FS &fs, const char * path, const char * message){
Serial.printf("Writing file: %s\r\n", path);

File file = fs.open(path, FILE_WRITE);
if(!file){
    Serial.println("- failed to open file for writing");
    return;
}
if(file.print(message)){
    Serial.println("- file written");
} else {
    Serial.println("- frite failed");
}

}
void setup(){
Serial.begin(115200);
Serial.setDebugOutput(true);
if (FORMAT_FFAT) FFat.format();
if(!FFat.begin()){
Serial.println("FFat Mount Failed");
return;
}
writeFile(FFat, "/hello.txt", "Hello ");
writeFile(FFat, "/second.txt", "second\n");
}
void loop(){}
`

`READ :


#include "FFat.h"

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
Serial.printf("Listing directory: %s\r\n", dirname);

File root = fs.open(dirname);
if(!root){
    Serial.println("- failed to open directory");
    return;
}
if(!root.isDirectory()){
    Serial.println(" - not a directory");
    return;
}

File file = root.openNextFile();
while(file){
    if(file.isDirectory()){
        Serial.print("  DIR : ");
        Serial.println(file.name());
        if(levels){
            listDir(fs, file.name(), levels -1);
        }
    } else {
        Serial.print("  FILE: ");
        Serial.print(file.name());
        Serial.print("\tSIZE: ");
        Serial.println(file.size());
    }
    file = root.openNextFile();
}

}

void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path);
if(!file || file.isDirectory()){
Serial.println("- failed to open file for reading");
return;
}
Serial.println("- read from file:");
while(file.available()){
Serial.write(file.read());
}
}

void setup(){
Serial.begin(115200);
FFat.begin();
listDir(FFat, "/", 0);
readFile(FFat, "/hello.txt");
readFile(FFat, "/second.txt");
}

void loop(){}
`

RESULT :


`Listing directory: /
FILE: /hello.txt SIZE: 0
Reading file: /hello.txt

  • read from file:
    Reading file: /second.txt
  • failed to open file for reading
    `
    in spiffs this works normally .. once the first file works and the other does not and sometimes does not work any of the two .. tested on 3x ESP32 board (2x16MB 1x4MB)

@atanisoft
Copy link
Collaborator

@PC-maniak the problem you are running into is that SPIFFS does not cache file modifications and SD does (due to file size being very small). If you add file.flush() and/or file.close() inside writeFile() it should work as you expect (even on SPIFFS).

@PC-maniak
Copy link
Author

RESULT :
Listing directory: /
FILE: /hello.txt SIZE: 6
FILE: /second.txt SIZE: 7
Reading file: /hello.txt

  • read from file: Hello
    Reading file: /second.txt
  • read from file: second

I do not understand that file.flush(); file.close(); is not included in the FAT demonstration

thanks now it can close 👍

@atanisoft
Copy link
Collaborator

Glad that it sorted the issue for you, it should definitely be included in the examples (at least closing the file!). The in memory cache caused me a lot of grief when I was testing with SD via the IDF APIs (which is also used here for FATfs) until I added file flushing (which is implicit via close).

@lbernstone I think we should improve the examples to help avoid this, as you mentioned it is better practice to close the files anyway so I think we should add that (and possibly the flush call).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants