diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5cd2e656a4..212a1ab94c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -896,6 +896,8 @@ 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 95b4082446..d9253551a2 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, @@ -23,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, } { } @@ -42,6 +45,8 @@ void FS::Init() { return; } } + // Clean filesystem on boot + lfs_fs_gc(&lfs); #ifndef PINETIME_IS_RECOVERY VerifyResource(); @@ -109,6 +114,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); }; } } 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); } } 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