Skip to content

Commit 084123b

Browse files
authored
Using littlefs (#438)
* add submodule littlefs * base fs * Save settings using littlefs * Small fixes and suggestions from PR * More small fixes from PR suggestions * Code clean up * Change SpiNorFlash functions to be private in FS
1 parent 61a4642 commit 084123b

11 files changed

Lines changed: 369 additions & 130 deletions

File tree

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "src/libs/lvgl"]
22
path = src/libs/lvgl
33
url = https://github.com/joaquimorg/lvgl.git
4+
[submodule "src/libs/littlefs"]
5+
path = src/libs/littlefs
6+
url = https://github.com/littlefs-project/littlefs.git

src/CMakeLists.txt

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,13 @@ set(NIMBLE_SRC
166166
libs/mynewt-nimble/nimble/host/util/src/addr.c
167167
)
168168

169+
set(LITTLEFS_SRC
170+
libs/littlefs/lfs_util.h
171+
libs/littlefs/lfs.h
172+
libs/littlefs/lfs_util.c
173+
libs/littlefs/lfs.c
174+
)
175+
169176
set(LVGL_SRC
170177
libs/lv_conf.h
171178
libs/lvgl/lvgl.h
@@ -465,6 +472,7 @@ list(APPEND SOURCE_FILES
465472
components/motor/MotorController.cpp
466473
components/settings/Settings.cpp
467474
components/timer/TimerController.cpp
475+
components/fs/FS.cpp
468476
drivers/Cst816s.cpp
469477
FreeRTOS/port.c
470478
FreeRTOS/port_cmsis_systick.c
@@ -543,6 +551,7 @@ list(APPEND RECOVERY_SOURCE_FILES
543551
components/heartrate/Biquad.cpp
544552
components/heartrate/Ptagc.cpp
545553
components/motor/MotorController.cpp
554+
components/fs/FS.cpp
546555
)
547556

548557
list(APPEND RECOVERYLOADER_SOURCE_FILES
@@ -801,13 +810,25 @@ target_compile_options(lvgl PRIVATE
801810
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp>
802811
)
803812

813+
# LITTLEFS_SRC
814+
add_library(littlefs STATIC ${LITTLEFS_SRC})
815+
target_include_directories(littlefs SYSTEM PUBLIC . ../)
816+
target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS})
817+
target_compile_options(littlefs PRIVATE
818+
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3>
819+
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os>
820+
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3 -fno-rtti>
821+
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os -fno-rtti>
822+
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp>
823+
)
824+
804825
# Build autonomous binary (without support for bootloader)
805826
set(EXECUTABLE_NAME "pinetime-app")
806827
set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
807828
set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld")
808829
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})
809830
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME})
810-
target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl)
831+
target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs)
811832
target_compile_options(${EXECUTABLE_NAME} PUBLIC
812833
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
813834
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Os>
@@ -836,7 +857,7 @@ set(IMAGE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERSION_
836857
set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
837858
set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld")
838859
add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES})
839-
target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl)
860+
target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs)
840861
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME})
841862
target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
842863
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
@@ -872,7 +893,7 @@ endif()
872893
set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery")
873894
set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
874895
add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES})
875-
target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk)
896+
target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs)
876897
set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME})
877898
target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY")
878899
target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC
@@ -902,7 +923,7 @@ set(EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-${
902923
set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin)
903924
set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
904925
add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES})
905-
target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk)
926+
target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs)
906927
set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME})
907928
target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY")
908929
target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC

src/components/fs/FS.cpp

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#include "FS.h"
2+
#include <cstring>
3+
#include <littlefs/lfs.h>
4+
#include <lvgl/lvgl.h>
5+
6+
using namespace Pinetime::Controllers;
7+
8+
FS::FS(Pinetime::Drivers::SpiNorFlash& driver) :
9+
flashDriver{ driver },
10+
lfsConfig{
11+
.context = this,
12+
.read = SectorRead,
13+
.prog = SectorProg,
14+
.erase = SectorErase,
15+
.sync = SectorSync,
16+
17+
.read_size = 16,
18+
.prog_size = 8,
19+
.block_size = blockSize,
20+
.block_count = size / blockSize,
21+
.block_cycles = 1000u,
22+
23+
.cache_size = 16,
24+
.lookahead_size = 16,
25+
26+
.name_max = 50,
27+
.attr_max = 50,
28+
}
29+
{ }
30+
31+
32+
void FS::Init() {
33+
34+
// try mount
35+
int err = lfs_mount(&lfs, &lfsConfig);
36+
37+
// reformat if we can't mount the filesystem
38+
// this should only happen on the first boot
39+
if (err != LFS_ERR_OK) {
40+
lfs_format(&lfs, &lfsConfig);
41+
err = lfs_mount(&lfs, &lfsConfig);
42+
if (err != LFS_ERR_OK) {
43+
return;
44+
}
45+
}
46+
47+
#ifndef PINETIME_IS_RECOVERY
48+
VerifyResource();
49+
LVGLFileSystemInit();
50+
#endif
51+
52+
}
53+
54+
void FS::VerifyResource() {
55+
// validate the resource metadata
56+
resourcesValid = true;
57+
}
58+
59+
int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) {
60+
return lfs_file_open(&lfs, file_p, fileName, flags);
61+
}
62+
63+
int FS::FileClose(lfs_file_t* file_p) {
64+
return lfs_file_close(&lfs, file_p);
65+
}
66+
67+
int FS::FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size) {
68+
return lfs_file_read(&lfs, file_p, buff, size);
69+
}
70+
71+
int FS::FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size) {
72+
return lfs_file_write(&lfs, file_p, buff, size);
73+
}
74+
75+
int FS::FileSeek(lfs_file_t* file_p, uint32_t pos) {
76+
return lfs_file_seek(&lfs, file_p, pos, LFS_SEEK_SET);
77+
}
78+
79+
int FS::FileDelete(const char* fileName) {
80+
return lfs_remove(&lfs, fileName);
81+
}
82+
83+
84+
int FS::DirCreate(const char* path) {
85+
return lfs_mkdir(&lfs, path);
86+
}
87+
88+
// Delete directory and all files inside
89+
int FS::DirDelete(const char* path) {
90+
91+
lfs_dir_t lfs_dir;
92+
lfs_info entryInfo;
93+
94+
int err;
95+
err = lfs_dir_open(&lfs, &lfs_dir, path);
96+
if (err) {
97+
return err;
98+
}
99+
while (lfs_dir_read(&lfs, &lfs_dir, &entryInfo)) {
100+
lfs_remove(&lfs, entryInfo.name);
101+
}
102+
lfs_dir_close(&lfs, &lfs_dir);
103+
return LFS_ERR_OK;
104+
}
105+
106+
/*
107+
108+
----------- Interface between littlefs and SpiNorFlash -----------
109+
110+
*/
111+
int FS::SectorSync(const struct lfs_config* c) {
112+
return 0;
113+
}
114+
115+
int FS::SectorErase(const struct lfs_config* c, lfs_block_t block) {
116+
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
117+
const size_t address = startAddress + (block * blockSize);
118+
lfs.flashDriver.SectorErase(address);
119+
return lfs.flashDriver.EraseFailed() ? -1 : 0;
120+
}
121+
122+
int FS::SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size) {
123+
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
124+
const size_t address = startAddress + (block * blockSize) + off;
125+
lfs.flashDriver.Write(address, (uint8_t*) buffer, size);
126+
return lfs.flashDriver.ProgramFailed() ? -1 : 0;
127+
}
128+
129+
int FS::SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size) {
130+
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
131+
const size_t address = startAddress + (block * blockSize) + off;
132+
lfs.flashDriver.Read(address, static_cast<uint8_t*>(buffer), size);
133+
return 0;
134+
}
135+
136+
/*
137+
138+
----------- LVGL filesystem integration -----------
139+
140+
*/
141+
142+
namespace {
143+
lv_fs_res_t lvglOpen(lv_fs_drv_t* drv, void* file_p, const char* path, lv_fs_mode_t mode) {
144+
145+
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
146+
FS* filesys = static_cast<FS*>(drv->user_data);
147+
filesys->FileOpen(file, path, LFS_O_RDONLY);
148+
149+
if (file->type == 0) {
150+
return LV_FS_RES_FS_ERR;
151+
}
152+
else {
153+
return LV_FS_RES_OK;
154+
}
155+
}
156+
157+
lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) {
158+
FS* filesys = static_cast<FS*>(drv->user_data);
159+
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
160+
filesys->FileClose(file);
161+
162+
return LV_FS_RES_OK;
163+
}
164+
165+
lv_fs_res_t lvglRead(lv_fs_drv_t* drv, void* file_p, void* buf, uint32_t btr, uint32_t* br) {
166+
FS* filesys = static_cast<FS*>(drv->user_data);
167+
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
168+
filesys->FileRead(file, static_cast<uint8_t*>(buf), btr);
169+
*br = btr;
170+
return LV_FS_RES_OK;
171+
}
172+
173+
lv_fs_res_t lvglSeek(lv_fs_drv_t* drv, void* file_p, uint32_t pos) {
174+
FS* filesys = static_cast<FS*>(drv->user_data);
175+
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
176+
filesys->FileSeek(file, pos);
177+
return LV_FS_RES_OK;
178+
}
179+
}
180+
181+
void FS::LVGLFileSystemInit() {
182+
183+
lv_fs_drv_t fs_drv;
184+
lv_fs_drv_init(&fs_drv);
185+
186+
fs_drv.file_size = sizeof(lfs_file_t);
187+
fs_drv.letter = 'F';
188+
fs_drv.open_cb = lvglOpen;
189+
fs_drv.close_cb = lvglClose;
190+
fs_drv.read_cb = lvglRead;
191+
fs_drv.seek_cb = lvglSeek;
192+
193+
fs_drv.user_data = this;
194+
195+
lv_fs_drv_register(&fs_drv);
196+
197+
}

src/components/fs/FS.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include "drivers/SpiNorFlash.h"
5+
#include <littlefs/lfs.h>
6+
7+
namespace Pinetime {
8+
namespace Controllers {
9+
class FS {
10+
public:
11+
FS(Pinetime::Drivers::SpiNorFlash&);
12+
13+
void Init();
14+
void LVGLFileSystemInit();
15+
16+
int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags);
17+
int FileClose(lfs_file_t* file_p);
18+
int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size);
19+
int FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size);
20+
int FileSeek(lfs_file_t* file_p, uint32_t pos);
21+
22+
int FileDelete(const char* fileName);
23+
24+
int DirCreate(const char* path);
25+
int DirDelete(const char* path);
26+
27+
void VerifyResource();
28+
29+
private:
30+
31+
Pinetime::Drivers::SpiNorFlash& flashDriver;
32+
33+
/*
34+
* External Flash MAP (4 MBytes)
35+
*
36+
* 0x000000 +---------------------------------------+
37+
* | Bootloader Assets |
38+
* | 256 KBytes |
39+
* | |
40+
* 0x040000 +---------------------------------------+
41+
* | OTA |
42+
* | 464 KBytes |
43+
* | |
44+
* | |
45+
* | |
46+
* 0x0B4000 +---------------------------------------+
47+
* | File System |
48+
* | |
49+
* | |
50+
* | |
51+
* | |
52+
* 0x400000 +---------------------------------------+
53+
*
54+
*/
55+
static constexpr size_t startAddress = 0x0B4000;
56+
static constexpr size_t size = 0x3C0000;
57+
static constexpr size_t blockSize = 4096;
58+
59+
bool resourcesValid = false;
60+
const struct lfs_config lfsConfig;
61+
62+
lfs_t lfs;
63+
64+
static int SectorSync(const struct lfs_config* c);
65+
static int SectorErase(const struct lfs_config* c, lfs_block_t block);
66+
static int SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size);
67+
static int SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size);
68+
69+
};
70+
}
71+
}

0 commit comments

Comments
 (0)