mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	More documentation may still by worthwhile (design documentation?), but for now this provides a reasonable baseline. - readme - license - header documentation
		
			
				
	
	
		
			125 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ## The little filesystem
 | |
| 
 | |
| A little fail-safe filesystem designed for low ram/rom footprint.
 | |
| 
 | |
| **Fail-safe** - The littlefs is designed to work consistently with random power
 | |
| failures. During filesystem operations the storage on disk is always kept
 | |
| in a valid state. The filesystem also has strong copy-on-write garuntees.
 | |
| When updating a file, the original file will remain unmodified until the
 | |
| file is closed, or sync is called.
 | |
| 
 | |
| **Handles bad blocks** - While the littlefs does not implement static wear
 | |
| leveling, if the underlying block device reports write errors, the littlefs
 | |
| uses a form of dynamic wear leveling to manage blocks that go bad during
 | |
| the lifetime of the filesystem.
 | |
| 
 | |
| **Constrained memory** - The littlefs is designed to work in bounded memory,
 | |
| recursion is avoided, and dynamic memory is kept to a minimum. The littlefs
 | |
| allocates two fixed-size buffers for general operations, and one fixed-size
 | |
| buffer per file. If there is only ever one file in use, these buffers can be
 | |
| provided statically.
 | |
| 
 | |
| ## 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;
 | |
|     printf("boot_count: %ld\n", boot_count);
 | |
|     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 and resources we were using
 | |
|     lfs_unmount(&lfs);
 | |
| }
 | |
| ```
 | |
| 
 | |
| ## Usage
 | |
| 
 | |
| Detailed documentation (or at least as much detail as is currently available)
 | |
| can be cound in the comments in [lfs.h](lfs.h).
 | |
| 
 | |
| As you may have noticed, the 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 either
 | |
| 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. An important addition is that
 | |
| no file updates will actually be written to disk until a sync or close
 | |
| is called.
 | |
| 
 | |
| ## 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.
 | |
| 
 | |
| It should also be noted that the littlefs does not do anything to insure
 | |
| that the data written to disk is machine portable. It should be fine as
 | |
| long as the machines involved share endianness and don't have really
 | |
| strange padding requirements. If the question does come up, the littlefs
 | |
| metadata should be stored on disk in little-endian format.
 | |
| 
 | |
| ## 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
 | |
| ```
 |