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:
parent
61a4642221
commit
084123b752
|
@ -1,3 +1,6 @@
|
|||
[submodule "src/libs/lvgl"]
|
||||
path = src/libs/lvgl
|
||||
url = https://github.com/joaquimorg/lvgl.git
|
||||
[submodule "src/libs/littlefs"]
|
||||
path = src/libs/littlefs
|
||||
url = https://github.com/littlefs-project/littlefs.git
|
||||
|
|
|
@ -166,6 +166,13 @@ set(NIMBLE_SRC
|
|||
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
|
||||
libs/lv_conf.h
|
||||
libs/lvgl/lvgl.h
|
||||
|
@ -465,6 +472,7 @@ list(APPEND SOURCE_FILES
|
|||
components/motor/MotorController.cpp
|
||||
components/settings/Settings.cpp
|
||||
components/timer/TimerController.cpp
|
||||
components/fs/FS.cpp
|
||||
drivers/Cst816s.cpp
|
||||
FreeRTOS/port.c
|
||||
FreeRTOS/port_cmsis_systick.c
|
||||
|
@ -543,6 +551,7 @@ list(APPEND RECOVERY_SOURCE_FILES
|
|||
components/heartrate/Biquad.cpp
|
||||
components/heartrate/Ptagc.cpp
|
||||
components/motor/MotorController.cpp
|
||||
components/fs/FS.cpp
|
||||
)
|
||||
|
||||
list(APPEND RECOVERYLOADER_SOURCE_FILES
|
||||
|
@ -801,13 +810,25 @@ target_compile_options(lvgl PRIVATE
|
|||
$<$<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)
|
||||
set(EXECUTABLE_NAME "pinetime-app")
|
||||
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")
|
||||
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})
|
||||
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
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
|
||||
$<$<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(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld")
|
||||
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})
|
||||
target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
|
||||
|
@ -872,7 +893,7 @@ endif()
|
|||
set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery")
|
||||
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})
|
||||
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})
|
||||
target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY")
|
||||
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(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})
|
||||
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})
|
||||
target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY")
|
||||
target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
|
@ -4,108 +4,44 @@
|
|||
|
||||
using namespace Pinetime::Controllers;
|
||||
|
||||
struct SettingsHeader {
|
||||
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} {
|
||||
Settings::Settings(Pinetime::Controllers::FS& fs) : fs {fs} {
|
||||
}
|
||||
|
||||
void Settings::Init() {
|
||||
|
||||
// Load default settings from Flash
|
||||
LoadSettingsFromFlash();
|
||||
LoadSettingsFromFile();
|
||||
}
|
||||
|
||||
void Settings::SaveSettings() {
|
||||
|
||||
// verify if is necessary to save
|
||||
if (settingsChanged) {
|
||||
SaveSettingsToFlash();
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
settingsChanged = false;
|
||||
}
|
||||
|
||||
bool Settings::FindHeader() {
|
||||
SettingsHeader settingsHeader;
|
||||
uint8_t bufferHead[sizeof(settingsHeader)];
|
||||
void Settings::LoadSettingsFromFile() {
|
||||
SettingsData bufferSettings;
|
||||
lfs_file_t settingsFile;
|
||||
|
||||
for (uint8_t block = 0; block < 10; block++) {
|
||||
|
||||
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;
|
||||
if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Settings::ReadSettingsData() {
|
||||
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();
|
||||
fs.FileRead(&settingsFile, reinterpret_cast<uint8_t*>(&bufferSettings), sizeof(settings));
|
||||
fs.FileClose(&settingsFile);
|
||||
if ( bufferSettings.version == settingsVersion ) {
|
||||
settings = bufferSettings;
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::SaveSettingsToFlash() {
|
||||
void Settings::SaveSettingsToFile() {
|
||||
lfs_file_t settingsFile;
|
||||
|
||||
// calculate where to save...
|
||||
// mark current to inactive
|
||||
// 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);
|
||||
if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
settingsFlashBlock++;
|
||||
if (settingsFlashBlock > 9)
|
||||
settingsFlashBlock = 0;
|
||||
|
||||
EraseBlock();
|
||||
SetHeader(true);
|
||||
SaveSettingsData();
|
||||
fs.FileWrite(&settingsFile, reinterpret_cast<uint8_t*>(&settings), sizeof(settings));
|
||||
fs.FileClose(&settingsFile);
|
||||
}
|
||||
|
|
|
@ -2,25 +2,26 @@
|
|||
#include <cstdint>
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/brightness/BrightnessController.h"
|
||||
#include "drivers/SpiNorFlash.h"
|
||||
#include "components/fs/FS.h"
|
||||
#include "drivers/Cst816s.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class Settings {
|
||||
public:
|
||||
enum class ClockType { H24, H12 };
|
||||
enum class Vibration { ON, OFF };
|
||||
enum class WakeUpMode { None, SingleTap, DoubleTap, RaiseWrist };
|
||||
enum class ClockType : uint8_t { H24, H12 };
|
||||
enum class Vibration : uint8_t { ON, OFF };
|
||||
enum class WakeUpMode : uint8_t { None, SingleTap, DoubleTap, RaiseWrist };
|
||||
|
||||
Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash);
|
||||
Settings(Pinetime::Controllers::FS& fs);
|
||||
|
||||
void Init();
|
||||
void SaveSettings();
|
||||
|
||||
void SetClockFace(uint8_t face) {
|
||||
if (face != settings.clockFace)
|
||||
if (face != settings.clockFace) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.clockFace = face;
|
||||
};
|
||||
uint8_t GetClockFace() const {
|
||||
|
@ -42,8 +43,9 @@ namespace Pinetime {
|
|||
};
|
||||
|
||||
void SetClockType(ClockType clocktype) {
|
||||
if (clocktype != settings.clockType)
|
||||
if (clocktype != settings.clockType) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.clockType = clocktype;
|
||||
};
|
||||
ClockType GetClockType() const {
|
||||
|
@ -51,8 +53,9 @@ namespace Pinetime {
|
|||
};
|
||||
|
||||
void SetVibrationStatus(Vibration status) {
|
||||
if (status != settings.vibrationStatus)
|
||||
if (status != settings.vibrationStatus) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.vibrationStatus = status;
|
||||
};
|
||||
Vibration GetVibrationStatus() const {
|
||||
|
@ -60,8 +63,9 @@ namespace Pinetime {
|
|||
};
|
||||
|
||||
void SetScreenTimeOut(uint32_t timeout) {
|
||||
if (timeout != settings.screenTimeOut)
|
||||
if (timeout != settings.screenTimeOut) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.screenTimeOut = timeout;
|
||||
};
|
||||
uint32_t GetScreenTimeOut() const {
|
||||
|
@ -69,8 +73,9 @@ namespace Pinetime {
|
|||
};
|
||||
|
||||
void setWakeUpMode(WakeUpMode wakeUp) {
|
||||
if (wakeUp != settings.wakeUpMode)
|
||||
if (wakeUp != settings.wakeUpMode) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.wakeUpMode = wakeUp;
|
||||
};
|
||||
WakeUpMode getWakeUpMode() const {
|
||||
|
@ -78,8 +83,9 @@ namespace Pinetime {
|
|||
};
|
||||
|
||||
void SetBrightness(Controllers::BrightnessController::Levels level) {
|
||||
if (level != settings.brightLevel)
|
||||
if (level != settings.brightLevel) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.brightLevel = level;
|
||||
};
|
||||
Controllers::BrightnessController::Levels GetBrightness() const {
|
||||
|
@ -87,25 +93,29 @@ namespace Pinetime {
|
|||
};
|
||||
|
||||
void SetStepsGoal( uint32_t goal ) {
|
||||
if ( goal != settings.stepsGoal )
|
||||
if ( goal != settings.stepsGoal ) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.stepsGoal = goal;
|
||||
};
|
||||
|
||||
uint32_t GetStepsGoal() const { return settings.stepsGoal; };
|
||||
|
||||
private:
|
||||
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
|
||||
Pinetime::Controllers::FS& fs;
|
||||
|
||||
static constexpr uint32_t settingsVersion = 0x0001;
|
||||
struct SettingsData {
|
||||
|
||||
uint32_t version = settingsVersion;
|
||||
uint32_t stepsGoal = 10000;
|
||||
uint32_t screenTimeOut = 15000;
|
||||
|
||||
ClockType clockType = ClockType::H24;
|
||||
Vibration vibrationStatus = Vibration::ON;
|
||||
|
||||
uint8_t clockFace = 0;
|
||||
|
||||
uint32_t stepsGoal = 10000;
|
||||
uint32_t screenTimeOut = 15000;
|
||||
|
||||
WakeUpMode wakeUpMode = WakeUpMode::None;
|
||||
|
||||
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
|
||||
|
@ -117,20 +127,8 @@ namespace Pinetime {
|
|||
uint8_t appMenu = 0;
|
||||
uint8_t settingsMenu = 0;
|
||||
|
||||
// There are 10 blocks of reserved flash to save settings
|
||||
// to minimize wear, the recording is done in a rotating way by the 10 blocks
|
||||
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();
|
||||
void LoadSettingsFromFile();
|
||||
void SaveSettingsToFile();
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ead50807f1ca3fdf2da00b77a0ce02651ded2d13
|
|
@ -204,7 +204,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */
|
|||
|
||||
/* 1: Enable file system (might be required for images */
|
||||
// TODO: Enable FS
|
||||
#define LV_USE_FILESYSTEM 0
|
||||
#define LV_USE_FILESYSTEM 1
|
||||
#if LV_USE_FILESYSTEM
|
||||
/*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;
|
||||
|
@ -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.
|
||||
* However the opened images might consume additional RAM.
|
||||
* 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`)*/
|
||||
typedef void* lv_img_decoder_user_data_t;
|
||||
|
|
13
src/main.cpp
13
src/main.cpp
|
@ -35,6 +35,7 @@
|
|||
#include "components/motor/MotorController.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/heartrate/HeartRateController.h"
|
||||
#include "components/fs/FS.h"
|
||||
#include "drivers/Spi.h"
|
||||
#include "drivers/SpiMaster.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 pinPowerPresentIrq = 19;
|
||||
|
||||
Pinetime::Controllers::Settings settingsController {spiNorFlash};
|
||||
|
||||
Pinetime::Controllers::MotorController motorController {settingsController};
|
||||
|
||||
Pinetime::Controllers::HeartRateController heartRateController;
|
||||
Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
|
||||
|
||||
|
@ -122,6 +119,11 @@ Pinetime::Controllers::NotificationManager notificationManager;
|
|||
Pinetime::Controllers::MotionController motionController;
|
||||
Pinetime::Controllers::TimerController timerController;
|
||||
|
||||
Pinetime::Controllers::FS fs {spiNorFlash};
|
||||
Pinetime::Controllers::Settings settingsController {fs};
|
||||
Pinetime::Controllers::MotorController motorController {settingsController};
|
||||
|
||||
|
||||
Pinetime::Applications::DisplayApp displayApp(lcd,
|
||||
lvgl,
|
||||
touchPanel,
|
||||
|
@ -155,7 +157,8 @@ Pinetime::System::SystemTask systemTask(spi,
|
|||
settingsController,
|
||||
heartRateController,
|
||||
displayApp,
|
||||
heartRateApp);
|
||||
heartRateApp,
|
||||
fs);
|
||||
|
||||
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
||||
if (pin == pinTouchIrq) {
|
||||
|
|
|
@ -59,7 +59,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
|
|||
Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::HeartRateController& heartRateController,
|
||||
Pinetime::Applications::DisplayApp& displayApp,
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp)
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp,
|
||||
Pinetime::Controllers::FS& fs)
|
||||
: spi {spi},
|
||||
lcd {lcd},
|
||||
spiNorFlash {spiNorFlash},
|
||||
|
@ -77,10 +78,11 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
|
|||
motionSensor {motionSensor},
|
||||
settingsController {settingsController},
|
||||
heartRateController{heartRateController},
|
||||
nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController),
|
||||
motionController{motionController},
|
||||
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();
|
||||
spiNorFlash.Init();
|
||||
spiNorFlash.Wakeup();
|
||||
|
||||
fs.Init();
|
||||
|
||||
nimbleController.Init();
|
||||
nimbleController.StartAdvertising();
|
||||
brightnessController.Init();
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "components/ble/NotificationManager.h"
|
||||
#include "components/motor/MotorController.h"
|
||||
#include "components/timer/TimerController.h"
|
||||
#include "components/fs/FS.h"
|
||||
|
||||
#ifdef PINETIME_IS_RECOVERY
|
||||
#include "displayapp/DisplayAppRecovery.h"
|
||||
#include "displayapp/DummyLittleVgl.h"
|
||||
|
@ -59,7 +61,8 @@ namespace Pinetime {
|
|||
Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::HeartRateController& heartRateController,
|
||||
Pinetime::Applications::DisplayApp& displayApp,
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp);
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp,
|
||||
Pinetime::Controllers::FS& fs);
|
||||
|
||||
void Start();
|
||||
void PushMessage(Messages msg);
|
||||
|
@ -103,13 +106,14 @@ namespace Pinetime {
|
|||
Pinetime::Drivers::Bma421& motionSensor;
|
||||
Pinetime::Controllers::Settings& settingsController;
|
||||
Pinetime::Controllers::HeartRateController& heartRateController;
|
||||
Pinetime::Controllers::NimbleController nimbleController;
|
||||
|
||||
Controllers::BrightnessController brightnessController;
|
||||
Pinetime::Controllers::MotionController& motionController;
|
||||
|
||||
Pinetime::Applications::DisplayApp& displayApp;
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp;
|
||||
|
||||
Pinetime::Controllers::FS& fs;
|
||||
Pinetime::Controllers::NimbleController nimbleController;
|
||||
|
||||
static constexpr uint8_t pinSpiSck = 2;
|
||||
static constexpr uint8_t pinSpiMosi = 3;
|
||||
|
|
Loading…
Reference in New Issue