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
This commit is contained in:
joaquim.org 2021-07-11 14:06:06 +01:00 committed by GitHub
parent 61a4642221
commit 084123b752
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 369 additions and 130 deletions

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "src/libs/lvgl"] [submodule "src/libs/lvgl"]
path = src/libs/lvgl path = src/libs/lvgl
url = https://github.com/joaquimorg/lvgl.git url = https://github.com/joaquimorg/lvgl.git
[submodule "src/libs/littlefs"]
path = src/libs/littlefs
url = https://github.com/littlefs-project/littlefs.git

View File

@ -166,6 +166,13 @@ set(NIMBLE_SRC
libs/mynewt-nimble/nimble/host/util/src/addr.c libs/mynewt-nimble/nimble/host/util/src/addr.c
) )
set(LITTLEFS_SRC
libs/littlefs/lfs_util.h
libs/littlefs/lfs.h
libs/littlefs/lfs_util.c
libs/littlefs/lfs.c
)
set(LVGL_SRC set(LVGL_SRC
libs/lv_conf.h libs/lv_conf.h
libs/lvgl/lvgl.h libs/lvgl/lvgl.h
@ -465,6 +472,7 @@ list(APPEND SOURCE_FILES
components/motor/MotorController.cpp components/motor/MotorController.cpp
components/settings/Settings.cpp components/settings/Settings.cpp
components/timer/TimerController.cpp components/timer/TimerController.cpp
components/fs/FS.cpp
drivers/Cst816s.cpp drivers/Cst816s.cpp
FreeRTOS/port.c FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c FreeRTOS/port_cmsis_systick.c
@ -543,6 +551,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/heartrate/Biquad.cpp components/heartrate/Biquad.cpp
components/heartrate/Ptagc.cpp components/heartrate/Ptagc.cpp
components/motor/MotorController.cpp components/motor/MotorController.cpp
components/fs/FS.cpp
) )
list(APPEND RECOVERYLOADER_SOURCE_FILES list(APPEND RECOVERYLOADER_SOURCE_FILES
@ -801,13 +810,25 @@ target_compile_options(lvgl PRIVATE
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp> $<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp>
) )
# LITTLEFS_SRC
add_library(littlefs STATIC ${LITTLEFS_SRC})
target_include_directories(littlefs SYSTEM PUBLIC . ../)
target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS})
target_compile_options(littlefs PRIVATE
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3 -fno-rtti>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os -fno-rtti>
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp>
)
# Build autonomous binary (without support for bootloader) # Build autonomous binary (without support for bootloader)
set(EXECUTABLE_NAME "pinetime-app") set(EXECUTABLE_NAME "pinetime-app")
set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld") set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld")
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME})
target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl) target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs)
target_compile_options(${EXECUTABLE_NAME} PUBLIC target_compile_options(${EXECUTABLE_NAME} PUBLIC
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Os> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Os>
@ -836,7 +857,7 @@ set(IMAGE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERSION_
set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld") set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld")
add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES}) add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES})
target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl) target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs)
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME}) set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME})
target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3> $<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
@ -872,7 +893,7 @@ endif()
set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery") set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery")
set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES}) add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES})
target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk) target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs)
set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME}) set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME})
target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY") target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY")
target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC
@ -902,7 +923,7 @@ set(EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-${
set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin) set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin)
set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES}) add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES})
target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk) target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs)
set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME}) set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME})
target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY") target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY")
target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC

197
src/components/fs/FS.cpp Normal file
View File

@ -0,0 +1,197 @@
#include "FS.h"
#include <cstring>
#include <littlefs/lfs.h>
#include <lvgl/lvgl.h>
using namespace Pinetime::Controllers;
FS::FS(Pinetime::Drivers::SpiNorFlash& driver) :
flashDriver{ driver },
lfsConfig{
.context = this,
.read = SectorRead,
.prog = SectorProg,
.erase = SectorErase,
.sync = SectorSync,
.read_size = 16,
.prog_size = 8,
.block_size = blockSize,
.block_count = size / blockSize,
.block_cycles = 1000u,
.cache_size = 16,
.lookahead_size = 16,
.name_max = 50,
.attr_max = 50,
}
{ }
void FS::Init() {
// try mount
int err = lfs_mount(&lfs, &lfsConfig);
// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err != LFS_ERR_OK) {
lfs_format(&lfs, &lfsConfig);
err = lfs_mount(&lfs, &lfsConfig);
if (err != LFS_ERR_OK) {
return;
}
}
#ifndef PINETIME_IS_RECOVERY
VerifyResource();
LVGLFileSystemInit();
#endif
}
void FS::VerifyResource() {
// validate the resource metadata
resourcesValid = true;
}
int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) {
return lfs_file_open(&lfs, file_p, fileName, flags);
}
int FS::FileClose(lfs_file_t* file_p) {
return lfs_file_close(&lfs, file_p);
}
int FS::FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size) {
return lfs_file_read(&lfs, file_p, buff, size);
}
int FS::FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size) {
return lfs_file_write(&lfs, file_p, buff, size);
}
int FS::FileSeek(lfs_file_t* file_p, uint32_t pos) {
return lfs_file_seek(&lfs, file_p, pos, LFS_SEEK_SET);
}
int FS::FileDelete(const char* fileName) {
return lfs_remove(&lfs, fileName);
}
int FS::DirCreate(const char* path) {
return lfs_mkdir(&lfs, path);
}
// Delete directory and all files inside
int FS::DirDelete(const char* path) {
lfs_dir_t lfs_dir;
lfs_info entryInfo;
int err;
err = lfs_dir_open(&lfs, &lfs_dir, path);
if (err) {
return err;
}
while (lfs_dir_read(&lfs, &lfs_dir, &entryInfo)) {
lfs_remove(&lfs, entryInfo.name);
}
lfs_dir_close(&lfs, &lfs_dir);
return LFS_ERR_OK;
}
/*
----------- Interface between littlefs and SpiNorFlash -----------
*/
int FS::SectorSync(const struct lfs_config* c) {
return 0;
}
int FS::SectorErase(const struct lfs_config* c, lfs_block_t block) {
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
const size_t address = startAddress + (block * blockSize);
lfs.flashDriver.SectorErase(address);
return lfs.flashDriver.EraseFailed() ? -1 : 0;
}
int FS::SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size) {
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
const size_t address = startAddress + (block * blockSize) + off;
lfs.flashDriver.Write(address, (uint8_t*) buffer, size);
return lfs.flashDriver.ProgramFailed() ? -1 : 0;
}
int FS::SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size) {
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
const size_t address = startAddress + (block * blockSize) + off;
lfs.flashDriver.Read(address, static_cast<uint8_t*>(buffer), size);
return 0;
}
/*
----------- LVGL filesystem integration -----------
*/
namespace {
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<lfs_file_t*>(file_p);
FS* filesys = static_cast<FS*>(drv->user_data);
filesys->FileOpen(file, path, LFS_O_RDONLY);
if (file->type == 0) {
return LV_FS_RES_FS_ERR;
}
else {
return LV_FS_RES_OK;
}
}
lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) {
FS* filesys = static_cast<FS*>(drv->user_data);
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
filesys->FileClose(file);
return LV_FS_RES_OK;
}
lv_fs_res_t lvglRead(lv_fs_drv_t* drv, void* file_p, void* buf, uint32_t btr, uint32_t* br) {
FS* filesys = static_cast<FS*>(drv->user_data);
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
filesys->FileRead(file, static_cast<uint8_t*>(buf), btr);
*br = btr;
return LV_FS_RES_OK;
}
lv_fs_res_t lvglSeek(lv_fs_drv_t* drv, void* file_p, uint32_t pos) {
FS* filesys = static_cast<FS*>(drv->user_data);
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
filesys->FileSeek(file, pos);
return LV_FS_RES_OK;
}
}
void FS::LVGLFileSystemInit() {
lv_fs_drv_t fs_drv;
lv_fs_drv_init(&fs_drv);
fs_drv.file_size = sizeof(lfs_file_t);
fs_drv.letter = 'F';
fs_drv.open_cb = lvglOpen;
fs_drv.close_cb = lvglClose;
fs_drv.read_cb = lvglRead;
fs_drv.seek_cb = lvglSeek;
fs_drv.user_data = this;
lv_fs_drv_register(&fs_drv);
}

71
src/components/fs/FS.h Normal file
View File

@ -0,0 +1,71 @@
#pragma once
#include <cstdint>
#include "drivers/SpiNorFlash.h"
#include <littlefs/lfs.h>
namespace Pinetime {
namespace Controllers {
class FS {
public:
FS(Pinetime::Drivers::SpiNorFlash&);
void Init();
void LVGLFileSystemInit();
int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags);
int FileClose(lfs_file_t* file_p);
int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size);
int FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size);
int FileSeek(lfs_file_t* file_p, uint32_t pos);
int FileDelete(const char* fileName);
int DirCreate(const char* path);
int DirDelete(const char* path);
void VerifyResource();
private:
Pinetime::Drivers::SpiNorFlash& flashDriver;
/*
* External Flash MAP (4 MBytes)
*
* 0x000000 +---------------------------------------+
* | Bootloader Assets |
* | 256 KBytes |
* | |
* 0x040000 +---------------------------------------+
* | OTA |
* | 464 KBytes |
* | |
* | |
* | |
* 0x0B4000 +---------------------------------------+
* | File System |
* | |
* | |
* | |
* | |
* 0x400000 +---------------------------------------+
*
*/
static constexpr size_t startAddress = 0x0B4000;
static constexpr size_t size = 0x3C0000;
static constexpr size_t blockSize = 4096;
bool resourcesValid = false;
const struct lfs_config lfsConfig;
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);
};
}
}

View File

@ -4,108 +4,44 @@
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
struct SettingsHeader { Settings::Settings(Pinetime::Controllers::FS& fs) : fs {fs} {
uint8_t isActive; // 0xF1 = Block is active, 0xF0 = Block is inactive
uint16_t version; // Current version, to verify if the saved data is for the current Version
};
#define HEADER_SIZE sizeof(SettingsHeader)
Settings::Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
} }
void Settings::Init() { void Settings::Init() {
// Load default settings from Flash // Load default settings from Flash
LoadSettingsFromFlash(); LoadSettingsFromFile();
} }
void Settings::SaveSettings() { void Settings::SaveSettings() {
// verify if is necessary to save // verify if is necessary to save
if (settingsChanged) { if (settingsChanged) {
SaveSettingsToFlash(); SaveSettingsToFile();
} }
settingsChanged = false; settingsChanged = false;
} }
bool Settings::FindHeader() { void Settings::LoadSettingsFromFile() {
SettingsHeader settingsHeader; SettingsData bufferSettings;
uint8_t bufferHead[sizeof(settingsHeader)]; lfs_file_t settingsFile;
for (uint8_t block = 0; block < 10; block++) { if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
return;
spiNorFlash.Read(settingsBaseAddr + (block * 0x1000), bufferHead, sizeof(settingsHeader));
std::memcpy(&settingsHeader, bufferHead, sizeof(settingsHeader));
if (settingsHeader.isActive == 0xF1 && settingsHeader.version == settingsVersion) {
settingsFlashBlock = block;
return true;
}
} }
return false; fs.FileRead(&settingsFile, reinterpret_cast<uint8_t*>(&bufferSettings), sizeof(settings));
} fs.FileClose(&settingsFile);
if ( bufferSettings.version == settingsVersion ) {
void Settings::ReadSettingsData() { settings = bufferSettings;
uint8_t bufferSettings[sizeof(settings)];
spiNorFlash.Read(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
std::memcpy(&settings, bufferSettings, sizeof(settings));
}
void Settings::EraseBlock() {
spiNorFlash.SectorErase(settingsBaseAddr + (settingsFlashBlock * 0x1000));
}
void Settings::SetHeader(bool state) {
SettingsHeader settingsHeader;
uint8_t bufferHead[sizeof(settingsHeader)];
settingsHeader.isActive = state ? 0xF1 : 0xF0;
settingsHeader.version = settingsVersion;
std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader));
spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader));
}
void Settings::SaveSettingsData() {
uint8_t bufferSettings[sizeof(settings)];
std::memcpy(bufferSettings, &settings, sizeof(settings));
spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
}
void Settings::LoadSettingsFromFlash() {
if (settingsFlashBlock == 99) {
// Find current Block, if can't find use default settings and set block to 0 ans save !
if (FindHeader()) {
ReadSettingsData();
} else {
SaveSettingsToFlash();
}
} else {
// Read Settings from flash...
// never used :)
ReadSettingsData();
} }
} }
void Settings::SaveSettingsToFlash() { void Settings::SaveSettingsToFile() {
lfs_file_t settingsFile;
// calculate where to save... if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
// mark current to inactive return;
// erase the new location and save
// set settingsFlashBlock
// if first time hever, only saves to block 0 and set settingsFlashBlock
if (settingsFlashBlock != 99) {
SetHeader(false);
} }
fs.FileWrite(&settingsFile, reinterpret_cast<uint8_t*>(&settings), sizeof(settings));
settingsFlashBlock++; fs.FileClose(&settingsFile);
if (settingsFlashBlock > 9)
settingsFlashBlock = 0;
EraseBlock();
SetHeader(true);
SaveSettingsData();
} }

View File

@ -2,25 +2,26 @@
#include <cstdint> #include <cstdint>
#include "components/datetime/DateTimeController.h" #include "components/datetime/DateTimeController.h"
#include "components/brightness/BrightnessController.h" #include "components/brightness/BrightnessController.h"
#include "drivers/SpiNorFlash.h" #include "components/fs/FS.h"
#include "drivers/Cst816s.h" #include "drivers/Cst816s.h"
namespace Pinetime { namespace Pinetime {
namespace Controllers { namespace Controllers {
class Settings { class Settings {
public: public:
enum class ClockType { H24, H12 }; enum class ClockType : uint8_t { H24, H12 };
enum class Vibration { ON, OFF }; enum class Vibration : uint8_t { ON, OFF };
enum class WakeUpMode { None, SingleTap, DoubleTap, RaiseWrist }; enum class WakeUpMode : uint8_t { None, SingleTap, DoubleTap, RaiseWrist };
Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash); Settings(Pinetime::Controllers::FS& fs);
void Init(); void Init();
void SaveSettings(); void SaveSettings();
void SetClockFace(uint8_t face) { void SetClockFace(uint8_t face) {
if (face != settings.clockFace) if (face != settings.clockFace) {
settingsChanged = true; settingsChanged = true;
}
settings.clockFace = face; settings.clockFace = face;
}; };
uint8_t GetClockFace() const { uint8_t GetClockFace() const {
@ -42,8 +43,9 @@ namespace Pinetime {
}; };
void SetClockType(ClockType clocktype) { void SetClockType(ClockType clocktype) {
if (clocktype != settings.clockType) if (clocktype != settings.clockType) {
settingsChanged = true; settingsChanged = true;
}
settings.clockType = clocktype; settings.clockType = clocktype;
}; };
ClockType GetClockType() const { ClockType GetClockType() const {
@ -51,8 +53,9 @@ namespace Pinetime {
}; };
void SetVibrationStatus(Vibration status) { void SetVibrationStatus(Vibration status) {
if (status != settings.vibrationStatus) if (status != settings.vibrationStatus) {
settingsChanged = true; settingsChanged = true;
}
settings.vibrationStatus = status; settings.vibrationStatus = status;
}; };
Vibration GetVibrationStatus() const { Vibration GetVibrationStatus() const {
@ -60,8 +63,9 @@ namespace Pinetime {
}; };
void SetScreenTimeOut(uint32_t timeout) { void SetScreenTimeOut(uint32_t timeout) {
if (timeout != settings.screenTimeOut) if (timeout != settings.screenTimeOut) {
settingsChanged = true; settingsChanged = true;
}
settings.screenTimeOut = timeout; settings.screenTimeOut = timeout;
}; };
uint32_t GetScreenTimeOut() const { uint32_t GetScreenTimeOut() const {
@ -69,8 +73,9 @@ namespace Pinetime {
}; };
void setWakeUpMode(WakeUpMode wakeUp) { void setWakeUpMode(WakeUpMode wakeUp) {
if (wakeUp != settings.wakeUpMode) if (wakeUp != settings.wakeUpMode) {
settingsChanged = true; settingsChanged = true;
}
settings.wakeUpMode = wakeUp; settings.wakeUpMode = wakeUp;
}; };
WakeUpMode getWakeUpMode() const { WakeUpMode getWakeUpMode() const {
@ -78,8 +83,9 @@ namespace Pinetime {
}; };
void SetBrightness(Controllers::BrightnessController::Levels level) { void SetBrightness(Controllers::BrightnessController::Levels level) {
if (level != settings.brightLevel) if (level != settings.brightLevel) {
settingsChanged = true; settingsChanged = true;
}
settings.brightLevel = level; settings.brightLevel = level;
}; };
Controllers::BrightnessController::Levels GetBrightness() const { Controllers::BrightnessController::Levels GetBrightness() const {
@ -87,25 +93,29 @@ namespace Pinetime {
}; };
void SetStepsGoal( uint32_t goal ) { void SetStepsGoal( uint32_t goal ) {
if ( goal != settings.stepsGoal ) if ( goal != settings.stepsGoal ) {
settingsChanged = true; settingsChanged = true;
}
settings.stepsGoal = goal; settings.stepsGoal = goal;
}; };
uint32_t GetStepsGoal() const { return settings.stepsGoal; }; uint32_t GetStepsGoal() const { return settings.stepsGoal; };
private: private:
Pinetime::Drivers::SpiNorFlash& spiNorFlash; Pinetime::Controllers::FS& fs;
static constexpr uint32_t settingsVersion = 0x0001;
struct SettingsData { struct SettingsData {
uint32_t version = settingsVersion;
uint32_t stepsGoal = 10000;
uint32_t screenTimeOut = 15000;
ClockType clockType = ClockType::H24; ClockType clockType = ClockType::H24;
Vibration vibrationStatus = Vibration::ON; Vibration vibrationStatus = Vibration::ON;
uint8_t clockFace = 0; uint8_t clockFace = 0;
uint32_t stepsGoal = 10000;
uint32_t screenTimeOut = 15000;
WakeUpMode wakeUpMode = WakeUpMode::None; WakeUpMode wakeUpMode = WakeUpMode::None;
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
@ -117,20 +127,8 @@ namespace Pinetime {
uint8_t appMenu = 0; uint8_t appMenu = 0;
uint8_t settingsMenu = 0; uint8_t settingsMenu = 0;
// There are 10 blocks of reserved flash to save settings void LoadSettingsFromFile();
// to minimize wear, the recording is done in a rotating way by the 10 blocks void SaveSettingsToFile();
uint8_t settingsFlashBlock = 99; // default to indicate it needs to find the active block
static constexpr uint32_t settingsBaseAddr = 0x3F6000; // Flash Settings Location
static constexpr uint16_t settingsVersion = 0x0100; // Flash Settings Version
bool FindHeader();
void ReadSettingsData();
void EraseBlock();
void SetHeader(bool state);
void SaveSettingsData();
void LoadSettingsFromFlash();
void SaveSettingsToFlash();
}; };
} }
} }

1
src/libs/littlefs Submodule

@ -0,0 +1 @@
Subproject commit ead50807f1ca3fdf2da00b77a0ce02651ded2d13

View File

@ -204,7 +204,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */
/* 1: Enable file system (might be required for images */ /* 1: Enable file system (might be required for images */
// TODO: Enable FS // TODO: Enable FS
#define LV_USE_FILESYSTEM 0 #define LV_USE_FILESYSTEM 1
#if LV_USE_FILESYSTEM #if LV_USE_FILESYSTEM
/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/ /*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/
typedef void * lv_fs_drv_user_data_t; typedef void * lv_fs_drv_user_data_t;
@ -236,7 +236,7 @@ typedef void * lv_fs_drv_user_data_t;
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. * With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
* However the opened images might consume additional RAM. * However the opened images might consume additional RAM.
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */ * LV_IMG_CACHE_DEF_SIZE must be >= 1 */
#define LV_IMG_CACHE_DEF_SIZE 1 #define LV_IMG_CACHE_DEF_SIZE 6
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/ /*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/
typedef void* lv_img_decoder_user_data_t; typedef void* lv_img_decoder_user_data_t;

View File

@ -35,6 +35,7 @@
#include "components/motor/MotorController.h" #include "components/motor/MotorController.h"
#include "components/datetime/DateTimeController.h" #include "components/datetime/DateTimeController.h"
#include "components/heartrate/HeartRateController.h" #include "components/heartrate/HeartRateController.h"
#include "components/fs/FS.h"
#include "drivers/Spi.h" #include "drivers/Spi.h"
#include "drivers/SpiMaster.h" #include "drivers/SpiMaster.h"
#include "drivers/SpiNorFlash.h" #include "drivers/SpiNorFlash.h"
@ -108,10 +109,6 @@ void ble_manager_set_ble_disconnection_callback(void (*disconnection)());
static constexpr uint8_t pinTouchIrq = 28; static constexpr uint8_t pinTouchIrq = 28;
static constexpr uint8_t pinPowerPresentIrq = 19; static constexpr uint8_t pinPowerPresentIrq = 19;
Pinetime::Controllers::Settings settingsController {spiNorFlash};
Pinetime::Controllers::MotorController motorController {settingsController};
Pinetime::Controllers::HeartRateController heartRateController; Pinetime::Controllers::HeartRateController heartRateController;
Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController); Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
@ -122,6 +119,11 @@ Pinetime::Controllers::NotificationManager notificationManager;
Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::MotionController motionController;
Pinetime::Controllers::TimerController timerController; Pinetime::Controllers::TimerController timerController;
Pinetime::Controllers::FS fs {spiNorFlash};
Pinetime::Controllers::Settings settingsController {fs};
Pinetime::Controllers::MotorController motorController {settingsController};
Pinetime::Applications::DisplayApp displayApp(lcd, Pinetime::Applications::DisplayApp displayApp(lcd,
lvgl, lvgl,
touchPanel, touchPanel,
@ -155,7 +157,8 @@ Pinetime::System::SystemTask systemTask(spi,
settingsController, settingsController,
heartRateController, heartRateController,
displayApp, displayApp,
heartRateApp); heartRateApp,
fs);
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
if (pin == pinTouchIrq) { if (pin == pinTouchIrq) {

View File

@ -59,7 +59,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Controllers::Settings& settingsController, Controllers::Settings& settingsController,
Pinetime::Controllers::HeartRateController& heartRateController, Pinetime::Controllers::HeartRateController& heartRateController,
Pinetime::Applications::DisplayApp& displayApp, Pinetime::Applications::DisplayApp& displayApp,
Pinetime::Applications::HeartRateTask& heartRateApp) Pinetime::Applications::HeartRateTask& heartRateApp,
Pinetime::Controllers::FS& fs)
: spi {spi}, : spi {spi},
lcd {lcd}, lcd {lcd},
spiNorFlash {spiNorFlash}, spiNorFlash {spiNorFlash},
@ -77,10 +78,11 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
motionSensor {motionSensor}, motionSensor {motionSensor},
settingsController {settingsController}, settingsController {settingsController},
heartRateController{heartRateController}, heartRateController{heartRateController},
nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController),
motionController{motionController}, motionController{motionController},
displayApp{displayApp}, displayApp{displayApp},
heartRateApp(heartRateApp) { heartRateApp(heartRateApp),
fs{fs},
nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) {
} }
@ -107,6 +109,9 @@ void SystemTask::Work() {
spi.Init(); spi.Init();
spiNorFlash.Init(); spiNorFlash.Init();
spiNorFlash.Wakeup(); spiNorFlash.Wakeup();
fs.Init();
nimbleController.Init(); nimbleController.Init();
nimbleController.StartAdvertising(); nimbleController.StartAdvertising();
brightnessController.Init(); brightnessController.Init();

View File

@ -16,6 +16,8 @@
#include "components/ble/NotificationManager.h" #include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h" #include "components/motor/MotorController.h"
#include "components/timer/TimerController.h" #include "components/timer/TimerController.h"
#include "components/fs/FS.h"
#ifdef PINETIME_IS_RECOVERY #ifdef PINETIME_IS_RECOVERY
#include "displayapp/DisplayAppRecovery.h" #include "displayapp/DisplayAppRecovery.h"
#include "displayapp/DummyLittleVgl.h" #include "displayapp/DummyLittleVgl.h"
@ -59,7 +61,8 @@ namespace Pinetime {
Controllers::Settings& settingsController, Controllers::Settings& settingsController,
Pinetime::Controllers::HeartRateController& heartRateController, Pinetime::Controllers::HeartRateController& heartRateController,
Pinetime::Applications::DisplayApp& displayApp, Pinetime::Applications::DisplayApp& displayApp,
Pinetime::Applications::HeartRateTask& heartRateApp); Pinetime::Applications::HeartRateTask& heartRateApp,
Pinetime::Controllers::FS& fs);
void Start(); void Start();
void PushMessage(Messages msg); void PushMessage(Messages msg);
@ -103,13 +106,14 @@ namespace Pinetime {
Pinetime::Drivers::Bma421& motionSensor; Pinetime::Drivers::Bma421& motionSensor;
Pinetime::Controllers::Settings& settingsController; Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::HeartRateController& heartRateController; Pinetime::Controllers::HeartRateController& heartRateController;
Pinetime::Controllers::NimbleController nimbleController;
Controllers::BrightnessController brightnessController; Controllers::BrightnessController brightnessController;
Pinetime::Controllers::MotionController& motionController; Pinetime::Controllers::MotionController& motionController;
Pinetime::Applications::DisplayApp& displayApp; Pinetime::Applications::DisplayApp& displayApp;
Pinetime::Applications::HeartRateTask& heartRateApp; Pinetime::Applications::HeartRateTask& heartRateApp;
Pinetime::Controllers::FS& fs;
Pinetime::Controllers::NimbleController nimbleController;
static constexpr uint8_t pinSpiSck = 2; static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3; static constexpr uint8_t pinSpiMosi = 3;