Looking for documentation/usage info for LittleFS

ChrisCurl

Active member
I see there are a few examples here:

https://github.com/PaulStoffregen/LittleFS/tree/main/examples

But it looks like there are a bunch of LittleFS types available ...

//LittleFS_QSPIFlash myfs;
//LittleFS_Program myfs;
//LittleFS_SPIFlash myfs;
//LittleFS_SPIFram myfs;
//LittleFS_SPINAND myfs;
LittleFS_QPINAND myfs;

What are all those? How do I decide which one to use?
Is there a simple example of how to use LittleFS? Just open/read/write/close?

I have very modest/simple need: to be able to read and write a few text files to the Teensy4.0 flash with no performance constraints or requirements. They will be very small files, and only a few of them, maybe 10 files at most, and I'd be surprised if the total storage ever exceeded 20K.

Please help, thanks
 
It is part of pending beta - there is a dedicated thread where it developed.

If reading code works look into LFSIntegrity sketch. It enables one type at a time and performs various operations.

Each of the indicated types cover one of the available Media types - some notes below - actual supported chips indicated in the library header:
Code:
[B]T_4.1 soldered QSPI FLASH [NOR][/B]:: //LittleFS_QSPIFlash myfs;
[B]Teensy PCB PROGRAM flash - Works until new program upload when flash is Wiped[/B]:: //LittleFS_Program myfs;
[B]SPI CONNECTED Flash chip [NOR][/B]:: //LittleFS_SPIFlash myfs;
[B]SPI CONNECTED FRAM/MRAM  chip [/B]:: //LittleFS_SPIFram myfs;
[B]SPI CONNECTED NAND Flash chip[/B] :: //LittleFS_SPINAND myfs;
[B]T_4.1 soldered QSPI NAND Flash chip [/B]:: LittleFS_QPINAND myfs;

Other type is RAM that can be QSPI PSRAM or MCU RAM depending on the supplied pointer - only works while powered.

UPDATED BOLD on type summary details

And a link to the 34 PAGE >> pjrc.com/threads/58033-LittleFS-port-to-Teensy-SPIFlash
 
Last edited:
@defragster has done a lot more playing with and testing of LittleFS than I have.

I have mostly played with it, in trying to integrate it with some other pieces like MTP...
As he mentioned, right now the main documentation is the other thread and the code.

But some hints:
When you see a name like LittleFS_QSPIFlash myfs
The ones that have _Q... Are for Quad SPI, which is T4.1 specific, when you have an external flash installed, like the WINBOND shown in the memory section of the T4.1 page:
https://www.pjrc.com/store/teensy41.html#memory

The: LittleFS_Program - uses part of your chips flash memory (unused part after where your program is stored). I believe the part just below reserved EEPROM. Warning currently when you download a new program this area will be overwritten.

Also there are a few different memory architectures that different chips have, like NOR versus NAND. I believe that the ones with names like LittleFS_SPIFlash are NOR and in this case addressed by normal SPI. And for example may have optionally on Audio card, or are on PropShield... And ones that have names like LittleFS_SPINAND are NAND memory again in this case uses SPI... There is also one that uses QSPI.

...
 
Thanks folks. I don't need to solder on an external flash chip; I can use the internal Teensy flash. So it looks like I would use the 'LittleFS_Program' flavor. That gives me a start. And I'll look at the integrity example for hints.

My program is a Forth system for the Teensy, so, unless I need to fix a bug or add new primitives, I shouldn't have to reload the program onto the board.
 
Earlier you said "with no performance constraints or requirements", so you should be aware that using the program memory for file storage requires stalling your program while the flash chip is busy doing erase or write operations. The write operations are typically on the scale of a dozen microseconds, but block erase can take a millisecond or longer. If you can't afford to stall your program, including all interrupts, for those lengths of time then you should probably use a dedicated chip.
 
For a test run of TD 1.54.Beta8 with IDE 1.8.14 I opened up :: T:\arduino_1.8.14\hardware\teensy\avr\libraries\LittleFS\examples\LFSintegrity\LFSintegrity.ino

Changes:

Only uncomment this line in the group : #define TEST_PROG

This line lower says use 6MB of FLASH space:
Code:
#elif defined(TEST_PROG)
[B]	if (!myfs.begin(1024 * 1024 * 6)) {[/B]

These lines show all libs used are from the installed TD 1.54.b8
Code:
Using library LittleFS at version 1.0.0 in folder: T:\arduino_1.8.14\hardware\teensy\avr\libraries\LittleFS 
Using library SPI at version 1.0 in folder: T:\arduino_1.8.14\hardware\teensy\avr\libraries\SPI 
Using library SdFat at version 2.0.5-beta.1 in folder: T:\arduino_1.8.14\hardware\teensy\avr\libraries\SdFat

Confirming MEDIA selected shows this after the HELP command list :: printDirectory PRO_DISK

Issuing a '4' command to do teste writes and deletes in directories shows general Write speed at 200 to 500+ KB/sec.

Doing that 'pollutes' the formatted Flash media.

Doing a 'w' will WIPE all dirs and Files

Doing 'f' will pre-Format all unused blocks, and it does take longer than I thought, though it looks like the reported time CALC is WRONG :(
>> (EDIT) because interrupts are OFF and it uses micros() for timing?
> if that is done on start any free space will be confirmed ready to write at that time.

Doing 'S' writes 2MB , then 's' verifies that file and deletes it, then 'f' format unused took about 13 seconds:
Code:
Start Big write of 2048000 Bytes.........................
Big write /0_2MBfile.txt took  3.94 Sec for 2048000 Bytes : file3.size()=2048000
	Big write KBytes per second 519.96 

Delete with read verify all #bigfile's
	Verify /0_2MBfile.txt bytes 2048000 : ..................................................	GOOD! >>  bytes 2048000
	Big read&compare KBytes per second 2620.33
 
Earlier you said "with no performance constraints or requirements", so you should be aware that using the program memory for file storage requires stalling your program while the flash chip is busy doing erase or write operations. The write operations are typically on the scale of a dozen microseconds, but block erase can take a millisecond or longer. If you can't afford to stall your program, including all interrupts, for those lengths of time then you should probably use a dedicated chip.
Good info. My use case is for those times where I am interactively writing code (user-defined words in Forth). Those words go into RAM, and would be lost when the board is powered down or restarted. So I want to be able to save those new definitions on the board so I can load them back in when the board restarts. So it is an action that I will take interactively, and not while the program is running.
 
I would queue to this post because I would try audio recording into external flash memory, avoiding the flash memory complete erase for every single-file write/rewrite operation. Belive that there is no option at the moment, but this longed for LittleFS..
 
So I am looking at the code for the integrity.ino example, and I have some questions:

LittleFS_Program myfs;

1. Does 'myfs.begin(1024 * 1024 * 6)' create and initialize the file system?
2. What does myfs.begin() do if there are already files stored there?
2. Or is myfs.lowLevelFormat('.') what creates the file system?
3. What is the difference between myfs.formatUnused( 0, 0 ) and myfs.lowLevelFormat('.')?
4. How can I tell if a file system has already been created when the board boots?
 
Last edited:
So I am looking at the code for the integrity.ino example, and I have some questions:

LittleFS_Program myfs;

1. Does 'myfs.begin(1024 * 1024 * 6)' create and initialize the file system?
2. What does myfs.begin() do if there are already files stored there?
2. Or is myfs.lowLevelFormat('.') what creates the file system?
3. How can I tell if a file system already exists when the board boots?
4. What is the difference between myfs.formatUnused( 0, 0 ) and myfs.lowLevelFormat('.')?

Using this for reference : T:\arduino-1.8.15\hardware\teensy\avr\libraries\LittleFS\src\LittleFS.cpp
> for :: T:\arduino-1.8.15\hardware\teensy\avr\libraries\LittleFS\examples\LFSintegrity\LFSintegrity.ino

All the " ::begin() " methods look to the class indicated Media.

Then those methods work as needed to:
> init the media interface for access
> mount() any existing image on the media for use
-> if that fails the media is formatted, then mounted
>Then returns 'true' if after that the media was left with a mounted image, otherwise false.

lowLevelFormat('.')
> requires mounted media
> will 'low level' format the media to an EMPTY state, destroying any stored data
> the '.' has the code give a progress indication printing the provided char
>> There is also "myfs.quickFormat();" that will reset the FS info marking it Empty ( losing data ) -but will not do a low level formatting of data blocks.

If the media held existing valid FS data it will be present on return from .begin()

As indicated above lowLevelFormat() [and myfs.quickFormat(); ] destroys any existing data
> where myfs.formatUnused preserves any existing FS data, but parses the media for any unused data blocks and assures they are left formatted. This is of value on Media where on the fly formatting would add significant time overhead before the data can be written when the media was not in a formatted state when called into use.
 
Thanks again. Last question: I don't see a File function to read a line of text ... do i just read one byte at a time until i hit my desired delimiter or zero bytes read (end of file)?
 
Thanks again. Last question: I don't see a File function to read a line of text ... do i just read one byte at a time until i hit my desired delimiter or zero bytes read (end of file)?

Can't say for sure, but FS.h is included but not seeing it inherits anything from FS? Feel free to try other functions - and if they fail - they are not included with needed mapping.
 
Back
Top