forked from Imagelibrary/littlefs
Compare commits
7 Commits
v2.9.1
...
link-pico-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0bbb8bc88b | ||
|
|
78082336e7 | ||
|
|
8336ecd203 | ||
|
|
68d28b5114 | ||
|
|
1bc14933b7 | ||
|
|
01b6a47ea8 | ||
|
|
749a45650f |
38
README.md
38
README.md
@@ -231,11 +231,25 @@ License Identifiers that are here available: http://spdx.org/licenses/
|
||||
to use littlefs in a Rust-friendly API, reaping the benefits of Rust's memory
|
||||
safety and other guarantees.
|
||||
|
||||
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
|
||||
implementation based on [littlefs-fuse]
|
||||
|
||||
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
|
||||
use with the MirageOS library operating system project. It is interoperable
|
||||
with the reference implementation, with some caveats.
|
||||
|
||||
- [littlefs-disk-img-viewer] - A memory-efficient web application for viewing
|
||||
littlefs disk images in your web browser.
|
||||
|
||||
- [mklfs] - A command line tool built by the [Lua RTOS] guys for making
|
||||
littlefs images from a host PC. Supports Windows, Mac OS, and Linux.
|
||||
- [mklfs] - A command line tool for creating littlefs images. Used in the Lua
|
||||
RTOS ecosystem.
|
||||
|
||||
- [mklittlefs] - A command line tool for creating littlefs images. Used in the
|
||||
ESP8266 and RP2040 ecosystem.
|
||||
|
||||
- [pico-littlefs-usb] - An interface for littlefs that emulates a FAT12
|
||||
filesystem over USB. Allows mounting littlefs on a host PC without additional
|
||||
drivers.
|
||||
|
||||
- [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed
|
||||
which already has block device drivers for most forms of embedded storage.
|
||||
@@ -254,27 +268,21 @@ License Identifiers that are here available: http://spdx.org/licenses/
|
||||
for microcontroller-scale devices. Due to limitations of FAT it can't provide
|
||||
power-loss resilience, but it does allow easy interop with PCs.
|
||||
|
||||
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
|
||||
use with the MirageOS library operating system project. It is interoperable
|
||||
with the reference implementation, with some caveats.
|
||||
|
||||
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
|
||||
implementation based on [littlefs-fuse]
|
||||
|
||||
[BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html
|
||||
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
|
||||
[littlefs-fuse]: https://github.com/geky/littlefs-fuse
|
||||
[FUSE]: https://github.com/libfuse/libfuse
|
||||
[littlefs-js]: https://github.com/geky/littlefs-js
|
||||
[littlefs-js-demo]:http://littlefs.geky.net/demo.html
|
||||
[littlefs-python]: https://pypi.org/project/littlefs-python/
|
||||
[littlefs2-rust]: https://crates.io/crates/littlefs2
|
||||
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
|
||||
[chamelon]: https://github.com/yomimono/chamelon
|
||||
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
|
||||
[mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src
|
||||
[Lua RTOS]: https://github.com/whitecatboard/Lua-RTOS-ESP32
|
||||
[mklittlefs]: https://github.com/earlephilhower/mklittlefs
|
||||
[pico-littlefs-usb]: https://github.com/oyama/pico-littlefs-usb
|
||||
[Mbed OS]: https://github.com/armmbed/mbed-os
|
||||
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html
|
||||
[SPIFFS]: https://github.com/pellepl/spiffs
|
||||
[Dhara]: https://github.com/dlbeer/dhara
|
||||
[ChaN's FatFs]: http://elm-chan.org/fsw/ff/00index_e.html
|
||||
[littlefs-python]: https://pypi.org/project/littlefs-python/
|
||||
[littlefs2-rust]: https://crates.io/crates/littlefs2
|
||||
[chamelon]: https://github.com/yomimono/chamelon
|
||||
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
|
||||
|
||||
2
lfs.c
2
lfs.c
@@ -688,7 +688,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
|
||||
if (lfs->lookahead.ckpoint <= 0) {
|
||||
LFS_ERROR("No more free space 0x%"PRIx32,
|
||||
(lfs->lookahead.start + lfs->lookahead.next)
|
||||
% lfs->cfg->block_count);
|
||||
% lfs->block_count);
|
||||
return LFS_ERR_NOSPC;
|
||||
}
|
||||
|
||||
|
||||
16
lfs.h
16
lfs.h
@@ -59,7 +59,8 @@ typedef uint32_t lfs_block_t;
|
||||
#endif
|
||||
|
||||
// Maximum size of custom attributes in bytes, may be redefined, but there is
|
||||
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022.
|
||||
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022. Stored
|
||||
// in superblock and must be respected by other littlefs drivers.
|
||||
#ifndef LFS_ATTR_MAX
|
||||
#define LFS_ATTR_MAX 1022
|
||||
#endif
|
||||
@@ -203,7 +204,8 @@ struct lfs_config {
|
||||
// program sizes.
|
||||
lfs_size_t block_size;
|
||||
|
||||
// Number of erasable blocks on the device.
|
||||
// Number of erasable blocks on the device. Defaults to block_count stored
|
||||
// on disk when zero.
|
||||
lfs_size_t block_count;
|
||||
|
||||
// Number of erase cycles before littlefs evicts metadata logs and moves
|
||||
@@ -252,18 +254,18 @@ struct lfs_config {
|
||||
|
||||
// Optional upper limit on length of file names in bytes. No downside for
|
||||
// larger names except the size of the info struct which is controlled by
|
||||
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
|
||||
// superblock and must be respected by other littlefs drivers.
|
||||
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX or name_max stored on
|
||||
// disk when zero.
|
||||
lfs_size_t name_max;
|
||||
|
||||
// Optional upper limit on files in bytes. No downside for larger files
|
||||
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored
|
||||
// in superblock and must be respected by other littlefs drivers.
|
||||
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX or file_max stored
|
||||
// on disk when zero.
|
||||
lfs_size_t file_max;
|
||||
|
||||
// Optional upper limit on custom attributes in bytes. No downside for
|
||||
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
|
||||
// LFS_ATTR_MAX when zero.
|
||||
// LFS_ATTR_MAX or attr_max stored on disk when zero.
|
||||
lfs_size_t attr_max;
|
||||
|
||||
// Optional upper limit on total space given to metadata pairs in bytes. On
|
||||
|
||||
@@ -8,17 +8,22 @@ defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.GC = [false, true]
|
||||
defines.COMPACT_THRESH = ['-1', '0', 'BLOCK_SIZE/2']
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
lfs_file_t files[FILES];
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -39,7 +44,7 @@ code = '''
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -62,17 +67,22 @@ defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.GC = [false, true]
|
||||
defines.COMPACT_THRESH = ['-1', '0', 'BLOCK_SIZE/2']
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
lfs_file_t file;
|
||||
@@ -91,7 +101,7 @@ code = '''
|
||||
lfs_unmount(&lfs) => 0;
|
||||
}
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -113,19 +123,24 @@ code = '''
|
||||
defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.CYCLES = [1, 10]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
lfs_file_t files[FILES];
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
|
||||
for (int c = 0; c < CYCLES; c++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -143,7 +158,7 @@ code = '''
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -159,7 +174,7 @@ code = '''
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -175,19 +190,24 @@ code = '''
|
||||
defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.CYCLES = [1, 10]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
|
||||
for (int c = 0; c < CYCLES; c++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
lfs_file_t file;
|
||||
@@ -232,10 +252,15 @@ code = '''
|
||||
|
||||
# exhaustion test
|
||||
[cases.test_alloc_exhaustion]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
|
||||
size_t size = strlen("exhaustion");
|
||||
@@ -263,7 +288,7 @@ code = '''
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
|
||||
size = strlen("exhaustion");
|
||||
lfs_file_size(&lfs, &file) => size;
|
||||
@@ -276,10 +301,15 @@ code = '''
|
||||
# exhaustion wraparound test
|
||||
[cases.test_alloc_exhaustion_wraparound]
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-4)) / 3)'
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT);
|
||||
@@ -317,7 +347,7 @@ code = '''
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
|
||||
size = strlen("exhaustion");
|
||||
lfs_file_size(&lfs, &file) => size;
|
||||
@@ -330,10 +360,15 @@ code = '''
|
||||
|
||||
# dir exhaustion test
|
||||
[cases.test_alloc_dir_exhaustion]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
|
||||
// find out max file size
|
||||
lfs_mkdir(&lfs, "exhaustiondir") => 0;
|
||||
|
||||
Reference in New Issue
Block a user