git describe --tags to find it): v4.0-dev-461-g17a3bdb8cxtensa-esp32-elf-gcc --version to find it): 1.22.0-80-g6c4433aIn my project i've creating fat fs via https://github.com/jkearins/ESP32_mkfatfs. This tool creates partition binary with WL FS v1 and after first mounting this partiton on device wl lib converts fs from v1 to v2.
After it some files, that was created by mkfatfs and burned during flash procedure are read and some new files are created (config.json). Everything works well even after reset (by button or by idf_monitor.py), but if i power off my dev board and power it again I'v got the following message: 'W (236) vfs_fat_spiflash: f_mount failed (13)' during boot.
If i set .format_if_mount_failed = true in mount_config where in esp_vfs_fat_spiflash_mount() returns 'ESP_OK', so in this case there is no way to determine if fs was mounted as is, or it was formated.
If i set .format_if_mount_failed = false in mount_config fs mounts without any warnings but i've got another porblem. Files, that was created by mkfatfs and burned during flash procedure reads without any problems, but files, that was created by my programm itself is not readable. Program opens a file (config.json), fopen, ftell, fseek, fread, fclose doesn't raise any errors but file is empty.
So, I can't understand why esp_vfs_fat_spiflash_mount() with .format_if_mount_failed = true not mounting fs but formats it while with .format_if_mount_failed = false it successfully mount fs? but files created on device is not readable.
Also there is a problem that esp_vfs_fat_spiflash_mount() and esp_vfs_fat_sdmmc_mount() doesn't return 'pdrv'. It will be very useful for futher usage of ff.h functions.
esp_err_t flash_fs_mount(void)
{
ESP_LOGD(TAG, "Initializing SPI flash FS");
const esp_vfs_fat_mount_config_t mount_config = {
.max_files = 4,
.format_if_mount_failed = false,
.allocation_unit_size = 512};
esp_err_t ret = esp_vfs_fat_spiflash_mount(FLASH_FS_MOUNT_PATH, "storage", &mount_config, &s_wl_handle);
if (ret != ESP_OK)
{
ESP_LOGE("SPI flash FS initialization error: %s", esp_err_to_name(ret));
return ret;
}
return ESP_OK;
}
esp_err_t config_save_file(const char *filename)
{
FILE *fp;
fp = fopen(filename, "w");
if (fp != NULL)
{
char *config = "{"data":"some data"}";
fprintf(fp, "%s", config);
fclose(fp);
ESP_LOGI(TAG, "Config successfully saved");
if (config)
{
vPortFree(config);
config = NULL;
}
return ESP_OK;
}
ESP_LOGE(TAG, "Config save error!");
return ESP_FAIL;
}
Hi @no1seman Yaroslav,
Could you please look into the file /components/wear_levelling/WL_Flash.cpp
and check if the lines around line 370 are equal to these:
this->state.version = 2;
this->state.pos = 0;
this->state.device_id = esp_random();
memset(this->state.reserved, 0, sizeof(this->state.reserved));
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
Or you have different one?
Thanks,
Dmitry
@dmitry1945, my WL_Flash.cpp have the following code near 370-th line:
this->state.version = 2;
this->state.pos = 0;
this->state.device_id = esp_random();
memset(this->state.reserved, 0, sizeof(this->state.reserved));
this->state.crc = crc32::crc32_le(WL_CFG_CRC_CONST, (uint8_t *)&this->state, WL_STATE_CRC_LEN_V2);
File length: 27224 bytes and it's the same as latest master branch.
@no1seman
thanks,
It's strange that you have this error.
I will look.
Thanks again.
Dmitry
@dmitry1945, I have to say that i'm using also SD card simultaneously with SPI flash WL FS.
May be that is the root of the problem?
@no1seman, I don't think so.
I will try to reproduce the problem. Then we will see. )
@no1seman, By the way, Yaroslav, could you please provide me an fatfs image that you make, as a file to flash?
@no1seman Yaroslav,
Thank! )
@dmitry1945,
seems to me that I found solution.
If I add setvbuf(fp, NULL, _IONBF, 0); before fprintf(fp, "%s", config); and fflush(fp); before fclose(fp); all begins to work perfectly.
Adding only fflush(fp); doesn't helps. So seems that the problem is in buffers fflush and/or file cache logic. When file closes by fclose() driver doesn't clean buffers/cache. In my opinion it's not proper behaivor, in GNU/Linux fclose() fixes all unwritten data to disk.
@no1seman Yaroslav, thanks a lot!
Great work!
Thanks!
@dmitry1945, today I'm tested fwrite() and it looks like that it has the same behavior. If you fwrite() some data and make fclose() after you can't get data written to the flash. Data will be avaible until device will not be off or correctly unmounted.
Are there any plans to fix it? Unbuffered writing is not a good way to write files...
@no1seman Yaroslav, I will fix it soon. I hope even today.
Dmitry
@dmitry1945, and whats about other problems:
@no1seman Hi Yaroslav,
I have tried to reproduce the error, and I'm not able to do this. I did it with SD card and without.
The simple application just waint 30 seconds, read file contents with expected name, if it exist, write file with the same name. Then reset (I do not call unmount).
.format_if_mount_failed = false,
Sector size is 512, mode - performance (safety also checked)
I do next:
I (30452) example: Mounting FAT filesystem
I (30452) wl_flash: updateV1_V2 Update from V1 to V2, crc=0x0e06d47d,
I (30462) wl_flash: updateV1_V2 max_pos=505, pos=117, state.ver=1, state2.ver=1
I (30712) example: Reading file step 1
E (30712) example: Failed to open file for reading
I (30712) example: Opening file
I (31052) example: File written
I (31052) example: Unmounting FAT filesystem
I (31052) example: DoneI see expected error because file was not created up to now.
Then I switch off the board, switch on and restart it with (make monitor).
I see next:
I (30452) example: Mounting FAT filesystem
I (30462) example: Reading file step 1
I (30462) example: Read from file: 'written using ESP-IDF v4.0-dev-288-g83d2ff07
c-dirty'
I (30462) example: Opening file
I (30902) example: File written
I (30912) example: Unmounting FAT filesystem
I (30912) example: DoneNow I see the that file contains the data as expected.
I simply not able to reproduce your problem. Could you provide me the stack size that you are using for your operations?
V1 and V2 are converted internally and should not affect FS. For fatfs there is no difference.
Thanks,
Dmitry
@dmitry1945,
seems to me that problem was in SPI_FLASH_ROM_DRIVER_PATCH. I'm using QIO flash SPI mode and, I didn't set it to =y, so file wrote to flash, but after full poweroff all written data was discarded. After switching on SPI_FLASH_ROM_DRIVER_PATCH=y all works fine. So the problem was not in WL FAT FS stack, but in SPI flash driver settings.
Thanks for your help.
P.S. There are some problems, I've mentioned in issues header:
@no1seman Yaroslav,
Thanks and respect for the info.
About point 4.
The conversion from V1 to V2 not affect the file system and only take few milliseconds to update from 1 to 2, that's why we did not change it up to now. I think we will do this in future, but not now.
About 3 the same. We will think.
@dmitry1945,
about point 4 - Ok, but point 3 - it's very uncomfortable. In my project i'm using both: SPI flash FS & SD card FS. If I need to use for example f_opendir() i can't use mount_path that I passed to esp_vfs_fat_sdmmc_mount() and for now the only way is to make own registration table. Why not to include s_pdrv into sdmmc_card_t structure?
Quoting the docs, esp_vfs_fat_sdmmc_mount is a convenience function. It is mainly intended to be used in example applications to make the code less verbose. It does very limited error checking, and developers are encouraged to look at its source code and incorporate more advanced versions into production applications. The steps which the application needs to take to use FATFS with an SD card are listed here: https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/fatfs.html#using-fatfs-with-vfs. This approach will also give you access to the pdrv value you are looking for.
On a related note, FATFS version 0.13b has added the ability to use a Unix-style path prefix as the volume name (via the FF_STR_VOLUME_ID configuration option). Once the version of FATFS used in IDF gets updated to the latest release, getting access to the pdrv might get easier. For example, esp_vfs_fat_sdmmc_mount may then set pdrv equal to the VFS mount point (base_path), which would be more transparent for the application.
@igrr, thanks for comments? I'll try to. Closing issue.
Most helpful comment
@dmitry1945,
seems to me that I found solution.
If I add setvbuf(fp, NULL, _IONBF, 0); before fprintf(fp, "%s", config); and fflush(fp); before fclose(fp); all begins to work perfectly.
Adding only fflush(fp); doesn't helps. So seems that the problem is in buffers fflush and/or file cache logic. When file closes by fclose() driver doesn't clean buffers/cache. In my opinion it's not proper behaivor, in GNU/Linux fclose() fixes all unwritten data to disk.