forked from InfiniTimeOrg/InfiniTime
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* 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
- Loading branch information
1 parent
61a4642
commit 084123b
Showing
11 changed files
with
369 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); | ||
|
||
}; | ||
} | ||
} |
Oops, something went wrong.