From b04d13ce656cf0bad7ccd928c8f02f28e5b57121 Mon Sep 17 00:00:00 2001 From: mark9064 <30447455+mark9064@users.noreply.github.com> Date: Fri, 27 Jun 2025 12:25:22 +0100 Subject: [PATCH 1/5] Upgrade LittleFS to v2.11.0 --- src/libs/littlefs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/littlefs b/src/libs/littlefs index ead50807f1..16ceb67934 160000 --- a/src/libs/littlefs +++ b/src/libs/littlefs @@ -1 +1 @@ -Subproject commit ead50807f1ca3fdf2da00b77a0ce02651ded2d13 +Subproject commit 16ceb6793449fa159f99aed4a766c2823f59cf3e From 1471301c3c76c5c1614a32661c5f0c433928475e Mon Sep 17 00:00:00 2001 From: mark9064 <30447455+mark9064@users.noreply.github.com> Date: Sat, 9 Sep 2023 21:07:37 +0100 Subject: [PATCH 2/5] Filesystem locking --- src/CMakeLists.txt | 1 + src/components/fs/FS.cpp | 12 ++++++++++++ src/components/fs/FS.h | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5cd2e656a4..f5d6e8c4d4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -896,6 +896,7 @@ target_compile_options(lvgl PRIVATE ) # LITTLEFS_SRC +add_definitions(-DLFS_THREADSAFE) add_library(littlefs STATIC ${LITTLEFS_SRC}) target_include_directories(littlefs SYSTEM PUBLIC . ../) target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 95b4082446..36b05a4b05 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -13,6 +13,8 @@ FS::FS(Pinetime::Drivers::SpiNorFlash& driver) .prog = SectorProg, .erase = SectorErase, .sync = SectorSync, + .lock = LockFilesystem, + .unlock = UnlockFilesystem, .read_size = 16, .prog_size = 8, @@ -109,6 +111,16 @@ lfs_ssize_t FS::GetFSSize() { return lfs_fs_size(&lfs); } +int FS::LockFilesystem(const struct lfs_config* c) { + Pinetime::Controllers::FS& lfs = *(static_cast(c->context)); + return xSemaphoreTake(lfs.fsMutex, portMAX_DELAY) == pdTRUE ? 0 : -1; +} + +int FS::UnlockFilesystem(const struct lfs_config* c) { + Pinetime::Controllers::FS& lfs = *(static_cast(c->context)); + return xSemaphoreGive(lfs.fsMutex) == pdTRUE ? 0 : -1; +} + /* ----------- Interface between littlefs and SpiNorFlash ----------- diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index aba3050935..b814cd6c59 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -3,6 +3,8 @@ #include #include "drivers/SpiNorFlash.h" #include +#include +#include namespace Pinetime { namespace Controllers { @@ -71,12 +73,15 @@ namespace Pinetime { bool resourcesValid = false; const struct lfs_config lfsConfig; + SemaphoreHandle_t fsMutex = xSemaphoreCreateMutex(); lfs_t lfs; static int SectorSync(const struct lfs_config* c); static int SectorErase(const struct lfs_config* c, lfs_block_t block); static int SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size); static int SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size); + static int LockFilesystem(const struct lfs_config* c); + static int UnlockFilesystem(const struct lfs_config* c); }; } } From 9de1d8d6feaae29713c8610f2c7f171c8e74aeb6 Mon Sep 17 00:00:00 2001 From: mark9064 <30447455+mark9064@users.noreply.github.com> Date: Thu, 29 Aug 2024 19:10:55 +0100 Subject: [PATCH 3/5] Map LittleFS errors to LVFS errors --- src/displayapp/LittleVgl.cpp | 70 +++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/displayapp/LittleVgl.cpp b/src/displayapp/LittleVgl.cpp index c6f6f78477..298f036cca 100644 --- a/src/displayapp/LittleVgl.cpp +++ b/src/displayapp/LittleVgl.cpp @@ -15,41 +15,79 @@ namespace { lv_theme_set_act(theme); } + constexpr lv_fs_res_t MapError(int err) { + switch (err) { + case LFS_ERR_OK: + return LV_FS_RES_OK; + case LFS_ERR_IO: + return LV_FS_RES_HW_ERR; + case LFS_ERR_CORRUPT: + return LV_FS_RES_FS_ERR; + case LFS_ERR_NOENT: + return LV_FS_RES_NOT_EX; + case LFS_ERR_EXIST: + return LV_FS_RES_FS_ERR; + case LFS_ERR_NOTDIR: + return LV_FS_RES_FS_ERR; + case LFS_ERR_ISDIR: + return LV_FS_RES_FS_ERR; + case LFS_ERR_NOTEMPTY: + return LV_FS_RES_FS_ERR; + case LFS_ERR_BADF: + return LV_FS_RES_INV_PARAM; + case LFS_ERR_FBIG: + return LV_FS_RES_FULL; + case LFS_ERR_INVAL: + return LV_FS_RES_INV_PARAM; + case LFS_ERR_NOSPC: + return LV_FS_RES_FULL; + case LFS_ERR_NOMEM: + return LV_FS_RES_OUT_OF_MEM; + case LFS_ERR_NOATTR: + return LV_FS_RES_UNKNOWN; + case LFS_ERR_NAMETOOLONG: + return LV_FS_RES_INV_PARAM; + default: + return LV_FS_RES_UNKNOWN; + } + } + lv_fs_res_t lvglOpen(lv_fs_drv_t* drv, void* file_p, const char* path, lv_fs_mode_t /*mode*/) { lfs_file_t* file = static_cast(file_p); Pinetime::Controllers::FS* filesys = static_cast(drv->user_data); int res = filesys->FileOpen(file, path, LFS_O_RDONLY); - if (res == 0) { - if (file->type == 0) { - return LV_FS_RES_FS_ERR; - } else { - return LV_FS_RES_OK; - } - } - return LV_FS_RES_NOT_EX; + return MapError(res); } lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) { Pinetime::Controllers::FS* filesys = static_cast(drv->user_data); lfs_file_t* file = static_cast(file_p); - filesys->FileClose(file); - - return LV_FS_RES_OK; + int res = filesys->FileClose(file); + return MapError(res); } lv_fs_res_t lvglRead(lv_fs_drv_t* drv, void* file_p, void* buf, uint32_t btr, uint32_t* br) { Pinetime::Controllers::FS* filesys = static_cast(drv->user_data); lfs_file_t* file = static_cast(file_p); - filesys->FileRead(file, static_cast(buf), btr); - *br = btr; - return LV_FS_RES_OK; + int res = filesys->FileRead(file, static_cast(buf), btr); + if (res >= 0) { + // br (bytes read) is allowed to be null + if (br != nullptr) { + *br = res; + } + return LV_FS_RES_OK; + } + return MapError(res); } lv_fs_res_t lvglSeek(lv_fs_drv_t* drv, void* file_p, uint32_t pos) { Pinetime::Controllers::FS* filesys = static_cast(drv->user_data); lfs_file_t* file = static_cast(file_p); - filesys->FileSeek(file, pos); - return LV_FS_RES_OK; + int res = filesys->FileSeek(file, pos); + if (res >= 0) { + return LV_FS_RES_OK; + } + return MapError(res); } } From 4eaca9d505d1650abb50be099e45974e7f14dd0e Mon Sep 17 00:00:00 2001 From: mark9064 <30447455+mark9064@users.noreply.github.com> Date: Sun, 26 Jan 2025 23:52:09 +0000 Subject: [PATCH 4/5] Clean LittleFS on boot --- src/components/fs/FS.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 36b05a4b05..eafec16732 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -44,6 +44,8 @@ void FS::Init() { return; } } + // Clean filesystem on boot + lfs_fs_gc(&lfs); #ifndef PINETIME_IS_RECOVERY VerifyResource(); From d6baa3452690f4d49501b0532b32836087df6278 Mon Sep 17 00:00:00 2001 From: mark9064 <30447455+mark9064@users.noreply.github.com> Date: Sun, 26 Jan 2025 23:48:42 +0000 Subject: [PATCH 5/5] Optimise LittleFS params --- src/CMakeLists.txt | 1 + src/components/fs/FS.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f5d6e8c4d4..212a1ab94c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -897,6 +897,7 @@ target_compile_options(lvgl PRIVATE # LITTLEFS_SRC add_definitions(-DLFS_THREADSAFE) +add_definitions(-DLFS_NAME_MAX=50) add_library(littlefs STATIC ${LITTLEFS_SRC}) target_include_directories(littlefs SYSTEM PUBLIC . ../) target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index eafec16732..d9253551a2 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -25,8 +25,9 @@ FS::FS(Pinetime::Drivers::SpiNorFlash& driver) .cache_size = 16, .lookahead_size = 16, - .name_max = 50, + .name_max = LFS_NAME_MAX, // Note: LFS_NAME_MAX is defined in src/CMakeLists.txt .attr_max = 50, + .metadata_max = 256, } { }