Open aliphys opened 7 months ago
LFS_NAME_MAX
in Arduino implementations of LittleFSLFS_NAME_MAX
in selected third party implementations of LittleFS
LFS_NAME_MAX
only applies to filenames... There is no limit on the path length other then the RAM and storage you have on your device.
LFS_NAME_MAX
value of less than 255.LFS_NAME_MAX
may be set to 255, build flags (-DLFS_NAME_MAX=XX
) may modify this during compilation. For example, in adafruit/Adafruit_nRF52_Arduino we have
build.flags.nrf= -DSOFTDEVICE_PRESENT -DARDUINO_NRF52_ADAFRUIT -DNRF52_SERIES -DDX_CC_TEE -DLFS_NAME_MAX=64 {compiler.optimization_flag} {build.debug_flags} {build.logger_flags} {build.sysview_flags} {compiler.arm.cmsis.c.flags} "-I{nordic.path}" "-I{nordic.path}/nrfx" "-I{nordic.path}/nrfx/hal" "-I{nordic.path}/nrfx/mdk" "-I{nordic.path}/nrfx/soc" "-I{nordic.path}/nrfx/drivers/include" "-I{nordic.path}/nrfx/drivers/src" "-I{nordic.path}/softdevice/{build.sd_name}_nrf52_{build.sd_version}_API/include" "-I{nordic.path}/softdevice/{build.sd_name}_nrf52_{build.sd_version}_API/include/nrf52" "-I{rtos.path}/Source/include" "-I{rtos.path}/config" "-I{rtos.path}/portable/GCC/nrf52" "-I{rtos.path}/portable/CMSIS/nrf52" "-I{build.core.path}/sysview/SEGGER" "-I{build.core.path}/sysview/Config" "-I{runtime.platform.path}/libraries/Adafruit_TinyUSB_Arduino/src/arduino"
LFS_NAME_MAX
value is overwritten to 32. This may create issues when interacting with images created with this tool. I did in fact spend 8 hours pin pointing that mklittlefs was the issue. My god...
Anyway, thanks for the notes here!
Following testing with both Renesas configurations (Portenta C33 with Vision Shield & Breakout) as well as mbed (Portenta H7 + Vision Shield), it is observed that the maximum path length is 255 characters. This limitation is present for LittleFS partitions on internal storage, SD and USB.
This limitation, if part of design, should be documented.
This is demonstrated through the test sketches below which creates a 255/256 character file (including the extension) and then reads it. As a representative example, the following two sketches are provided for the Portenta H7 with the Vision Shield and internal storage. Similar observations are made for the Portenta C33 as well as USB and SD storage.
255 Character Filename - PASS
Sketch
``` #include "Arduino_UnifiedStorage.h" #include "CRC.h" // https://github.com/RobTillaart/CRC InternalStorage storage; CRC8 crc; const char testCaseID[] = "AUS_SPIS_FNBLFS_009"; void setup() { Serial.begin(115200); while (!Serial); Serial.println("---"); Serial.print("Test Case ID: "); Serial.println(testCaseID); Serial.println("---"); Arduino_UnifiedStorage::debuggingModeEnabled = false; if (Arduino_UnifiedStorage::debuggingModeEnabled) { Serial.println("Arduino_UnifiedStorage debug messages ON."); } storage = InternalStorage(); storage.format(FS_LITTLEFS); if(!storage.begin()){ Serial.println("Error mounting storage device."); } // specify Test strings & CRC const char testContent[] = "Hello World!"; for (int i = 0; i < strlen(testContent); i++) { crc.add(testContent[i]); } uint8_t testContentCRC8 = crc.calc(); crc.reset(); Serial.println("testContent value:" + String(testContent) + ". With CRC value:" + String(testContentCRC8)); const char testFilename[] = "255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255.txt"; for (int i = 0; i < strlen(testFilename); i++) { crc.add(testFilename[i]); } uint8_t testFilenameCRC8 = crc.calc(); crc.reset(); Serial.println("testFilename value:" + String(testFilename) + ". With CRC value:" + String(testFilenameCRC8)); // Create empty file and set to WRITE mode Folder root = storage.getRootFolder(); UFile file1 = root.createFile(testFilename, FileMode::WRITE); file1.write(testContent); file1.changeMode(FileMode::READ); file1.seek(0); String dataRead = ""; while (file1.available()) { char data = file1.read(); crc.add(data); dataRead += data; } Serial.println(); uint8_t dataReadCRC = crc.calc(); Serial.println("Files found:"); std::vectorSerial Monitor
``` --- Test Case ID: AUS_SPIS_FNBLFS_009 --- testContent value:Hello World!. With CRC value:28 testFilename value:255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255.txt. With CRC value:127 Files found: [F] /internal/255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255chars255.txt Data read was Hello World! with CRC value 28 ```256 Character Filename - FAIL
Sketch
``` #include "Arduino_UnifiedStorage.h" #include "CRC.h" // https://github.com/RobTillaart/CRC InternalStorage storage; CRC8 crc; const char testCaseID[] = "AUS_SPIS_FNBLFS_010"; void setup() { Serial.begin(115200); while (!Serial); Serial.println("---"); Serial.print("Test Case ID: "); Serial.println(testCaseID); Serial.println("---"); Arduino_UnifiedStorage::debuggingModeEnabled = false; if (Arduino_UnifiedStorage::debuggingModeEnabled) { Serial.println("Arduino_UnifiedStorage debug messages ON."); } storage = InternalStorage(); storage.format(FS_LITTLEFS); if(!storage.begin()){ Serial.println("Error mounting storage device."); } // specify Test strings & CRC const char testContent[] = "Hello World!"; for (int i = 0; i < strlen(testContent); i++) { crc.add(testContent[i]); } uint8_t testContentCRC8 = crc.calc(); crc.reset(); Serial.println("testContent value:" + String(testContent) + ". With CRC value:" + String(testContentCRC8)); const char testFilename[] = "256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256c.txt"; for (int i = 0; i < strlen(testFilename); i++) { crc.add(testFilename[i]); } uint8_t testFilenameCRC8 = crc.calc(); crc.reset(); Serial.println("testFilename value:" + String(testFilename) + ". With CRC value:" + String(testFilenameCRC8)); // Create empty file and set to WRITE mode Folder root = storage.getRootFolder(); UFile file1 = root.createFile(testFilename, FileMode::WRITE); file1.write(testContent); file1.changeMode(FileMode::READ); file1.seek(0); String dataRead = ""; while (file1.available()) { char data = file1.read(); crc.add(data); dataRead += data; } Serial.println(); uint8_t dataReadCRC = crc.calc(); Serial.println("Files found:"); std::vectorSerial Monitor
``` --- Test Case ID: AUS_SPIS_FNBLFS_010 --- testContent value:Hello World!. With CRC value:28 testFilename value:256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256chars256c.txt. With CRC value:182 Files found: [F] /internal/ Data read was with CRC value 0 ```Additional information
On the Renasas core (Portenta C33), the LittleFS driver sets the maximum character length to 255 characters via LFS_NAME_MAX.
On the mbed core (Portenta H7), the LittleFS driver also sets the maximum character length to 255 characters via LFS_NAME_MAX.
In both cases for both the mbed and Renasas core, a
lfs_info
structure adds an addtion byteLFS_NAME_MAX+1
to account for a null terminated string that corresponds to the test outcome.