mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Interesting open-source projects that I've ran into around embedded storage. May be interesting to others in the embedded space. Added mklfs, SPIFFS, and Dhara. Also a thanks to jolivepetrus for posting the mklfs tool he put together.
		
			
				
	
	
		
			193 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ## The little filesystem
 | |
| 
 | |
| A little fail-safe filesystem designed for embedded systems.
 | |
| 
 | |
| ```
 | |
|    | | |     .---._____
 | |
|   .-----.   |          |
 | |
| --|o    |---| littlefs |
 | |
| --|     |---|          |
 | |
|   '-----'   '----------'
 | |
|    | | |
 | |
| ```
 | |
| 
 | |
| **Bounded RAM/ROM** - The littlefs is designed to work with a limited amount
 | |
| of memory. Recursion is avoided and dynamic memory is limited to configurable
 | |
| buffers that can be provided statically.
 | |
| 
 | |
| **Power-loss resilient** - The littlefs is designed for systems that may have
 | |
| random power failures. The littlefs has strong copy-on-write guarantees and
 | |
| storage on disk is always kept in a valid state.
 | |
| 
 | |
| **Wear leveling** - Since the most common form of embedded storage is erodible
 | |
| flash memories, littlefs provides a form of dynamic wear leveling for systems
 | |
| that can not fit a full flash translation layer.
 | |
| 
 | |
| ## Example
 | |
| 
 | |
| Here's a simple example that updates a file named `boot_count` every time
 | |
| main runs. The program can be interrupted at any time without losing track
 | |
| of how many times it has been booted and without corrupting the filesystem:
 | |
| 
 | |
| ``` c
 | |
| #include "lfs.h"
 | |
| 
 | |
| // variables used by the filesystem
 | |
| lfs_t lfs;
 | |
| lfs_file_t file;
 | |
| 
 | |
| // configuration of the filesystem is provided by this struct
 | |
| const struct lfs_config cfg = {
 | |
|     // block device operations
 | |
|     .read  = user_provided_block_device_read,
 | |
|     .prog  = user_provided_block_device_prog,
 | |
|     .erase = user_provided_block_device_erase,
 | |
|     .sync  = user_provided_block_device_sync,
 | |
| 
 | |
|     // block device configuration
 | |
|     .read_size = 16,
 | |
|     .prog_size = 16,
 | |
|     .block_size = 4096,
 | |
|     .block_count = 128,
 | |
|     .lookahead = 128,
 | |
| };
 | |
| 
 | |
| // entry point
 | |
| int main(void) {
 | |
|     // mount the filesystem
 | |
|     int err = lfs_mount(&lfs, &cfg);
 | |
| 
 | |
|     // reformat if we can't mount the filesystem
 | |
|     // this should only happen on the first boot
 | |
|     if (err) {
 | |
|         lfs_format(&lfs, &cfg);
 | |
|         lfs_mount(&lfs, &cfg);
 | |
|     }
 | |
| 
 | |
|     // read current count
 | |
|     uint32_t boot_count = 0;
 | |
|     lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
 | |
|     lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
 | |
| 
 | |
|     // update boot count
 | |
|     boot_count += 1;
 | |
|     lfs_file_rewind(&lfs, &file);
 | |
|     lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
 | |
| 
 | |
|     // remember the storage is not updated until the file is closed successfully
 | |
|     lfs_file_close(&lfs, &file);
 | |
| 
 | |
|     // release any resources we were using
 | |
|     lfs_unmount(&lfs);
 | |
| 
 | |
|     // print the boot count
 | |
|     printf("boot_count: %d\n", boot_count);
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Usage
 | |
| 
 | |
| Detailed documentation (or at least as much detail as is currently available)
 | |
| can be found in the comments in [lfs.h](lfs.h).
 | |
| 
 | |
| As you may have noticed, littlefs takes in a configuration structure that
 | |
| defines how the filesystem operates. The configuration struct provides the
 | |
| filesystem with the block device operations and dimensions, tweakable
 | |
| parameters that tradeoff memory usage for performance, and optional
 | |
| static buffers if the user wants to avoid dynamic memory.
 | |
| 
 | |
| The state of the littlefs is stored in the `lfs_t` type which is left up
 | |
| to the user to allocate, allowing multiple filesystems to be in use
 | |
| simultaneously. With the `lfs_t` and configuration struct, a user can
 | |
| format a block device or mount the filesystem.
 | |
| 
 | |
| Once mounted, the littlefs provides a full set of POSIX-like file and
 | |
| directory functions, with the deviation that the allocation of filesystem
 | |
| structures must be provided by the user.
 | |
| 
 | |
| All POSIX operations, such as remove and rename, are atomic, even in event
 | |
| of power-loss. Additionally, no file updates are actually committed to the
 | |
| filesystem until sync or close is called on the file.
 | |
| 
 | |
| ## Other notes
 | |
| 
 | |
| All littlefs have the potential to return a negative error code. The errors
 | |
| can be either one of those found in the `enum lfs_error` in [lfs.h](lfs.h),
 | |
| or an error returned by the user's block device operations.
 | |
| 
 | |
| In the configuration struct, the `prog` and `erase` function provided by the
 | |
| user may return a `LFS_ERR_CORRUPT` error if the implementation already can
 | |
| detect corrupt blocks. However, the wear leveling does not depend on the return
 | |
| code of these functions, instead all data is read back and checked for
 | |
| integrity.
 | |
| 
 | |
| If your storage caches writes, make sure that the provided `sync` function
 | |
| flushes all the data to memory and ensures that the next read fetches the data
 | |
| from memory, otherwise data integrity can not be guaranteed. If the `write`
 | |
| function does not perform caching, and therefore each `read` or `write` call
 | |
| hits the memory, the `sync` function can simply return 0.
 | |
| 
 | |
| ## Reference material
 | |
| 
 | |
| [DESIGN.md](DESIGN.md) - DESIGN.md contains a fully detailed dive into how
 | |
| littlefs actually works. I would encourage you to read it since the
 | |
| solutions and tradeoffs at work here are quite interesting.
 | |
| 
 | |
| [SPEC.md](SPEC.md) - SPEC.md contains the on-disk specification of littlefs
 | |
| with all the nitty-gritty details. Can be useful for developing tooling.
 | |
| 
 | |
| ## Testing
 | |
| 
 | |
| The littlefs comes with a test suite designed to run on a PC using the
 | |
| [emulated block device](emubd/lfs_emubd.h) found in the emubd directory.
 | |
| The tests assume a Linux environment and can be started with make:
 | |
| 
 | |
| ``` bash
 | |
| make test
 | |
| ```
 | |
| 
 | |
| ## License
 | |
| 
 | |
| The littlefs is provided under the [BSD-3-Clause](https://spdx.org/licenses/BSD-3-Clause.html)
 | |
| license. See [LICENSE.md](LICENSE.md) for more information. Contributions to
 | |
| this project are accepted under the same license.
 | |
| 
 | |
| Individual files contain the following tag instead of the full license text.
 | |
| 
 | |
|     SPDX-License-Identifier:    BSD-3-Clause
 | |
| 
 | |
| This enables machine processing of license information based on the SPDX
 | |
| License Identifiers that are here available: http://spdx.org/licenses/
 | |
| 
 | |
| ## Related projects
 | |
| 
 | |
| [Mbed OS](https://github.com/ARMmbed/mbed-os/tree/master/features/filesystem/littlefs) -
 | |
| The easiest way to get started with littlefs is to jump into [Mbed](https://os.mbed.com/),
 | |
| which already has block device drivers for most forms of embedded storage. The
 | |
| littlefs is available in Mbed OS as the [LittleFileSystem](https://os.mbed.com/docs/latest/reference/littlefilesystem.html)
 | |
| class.
 | |
| 
 | |
| [littlefs-fuse](https://github.com/geky/littlefs-fuse) - A [FUSE](https://github.com/libfuse/libfuse)
 | |
| wrapper for littlefs. The project allows you to mount littlefs directly on a
 | |
| Linux machine. Can be useful for debugging littlefs if you have an SD card
 | |
| handy.
 | |
| 
 | |
| [littlefs-js](https://github.com/geky/littlefs-js) - A javascript wrapper for
 | |
| littlefs. I'm not sure why you would want this, but it is handy for demos.
 | |
| You can see it in action [here](http://littlefs.geky.net/demo.html).
 | |
| 
 | |
| [mklfs](https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src) -
 | |
| A command line tool built by the [Lua RTOS](https://github.com/whitecatboard/Lua-RTOS-ESP32)
 | |
| guys for making littlefs images from a host PC. Supports Windows, Mac OS,
 | |
| and Linux.
 | |
| 
 | |
| [SPIFFS](https://github.com/pellepl/spiffs) - Another excellent embedded
 | |
| filesystem for NOR flash. As a more traditional logging filesystem with full
 | |
| static wear-leveling, SPIFFS will likely outperform littlefs on small
 | |
| memories such as the internal flash on microcontrollers.
 | |
| 
 | |
| [Dhara](https://github.com/dlbeer/dhara) - An interesting NAND flash
 | |
| translation layer designed for small MCUs. It offers static wear-leveling and
 | |
| power-resilience with only a fixed O(|address|) pointer structure stored on
 | |
| each block and in RAM.
 |