3#include <hardware/flash.h>
4#include <hardware/sync.h>
5#include <pico/multicore.h>
6#include <hardware/regs/addressmap.h>
11#include <pico/flash.h>
34 return (xSemaphoreTake(
lfs_mutex, portMAX_DELAY) == pdTRUE) ? 0 : -1;
38 return (xSemaphoreGive(
lfs_mutex) == pdTRUE) ? 0 : -1;
42 void *buffer, lfs_size_t size)
45 uintptr_t addr = self->
flashBase + block * c->block_size + off;
46 std::memcpy(buffer,
reinterpret_cast<const void *
>(addr), size);
52 const void *buffer, lfs_size_t size)
55#if (configNUM_CORES > 1)
63 const void *buffer, lfs_size_t size)
66 uintptr_t addr = self->
flashBase + block * c->block_size + off;
67 uint32_t ints = save_and_disable_interrupts();
68 flash_range_program(addr - XIP_BASE,
reinterpret_cast<const uint8_t *
>(buffer), size);
69 restore_interrupts(ints);
83 flash_range_program(params->addr, params->data, params->size);
93 uintptr_t addr = self->
getFlashBase() + block * c->block_size + off;
96 .
addr = addr - XIP_BASE,
97 .data =
static_cast<const uint8_t *
>(buffer),
100 return (result == PICO_OK) ? 0 : -1;
106 uintptr_t addr = self->
flashBase + block * c->block_size + off;
112#if (configNUM_CORES > 1)
122 uintptr_t addr = self->
flashBase + block * c->block_size;
123 uint32_t ints = save_and_disable_interrupts();
124 flash_range_erase(addr - XIP_BASE, c->block_size);
125 restore_interrupts(ints);
139 flash_range_erase(params->addr, params->size);
145 uintptr_t addr = self->
getFlashBase() + block * c->block_size;
148 .
addr = addr - XIP_BASE,
149 .size = c->block_size};
151 return (result == PICO_OK) ? 0 : -1;
180 config.sync = [](
const struct lfs_config *) ->
int
188 config.lookahead_size = 256;
189 config.block_cycles = 500;
190 config.compact_thresh = (lfs_size_t)-1;
191#if defined(LFS_THREADSAFE)
203 TRACE(
"[LittleFs] Already mounted\n");
206 TRACE(
"[LittleFs] Mounting LittleFS...\n");
210 printf(
"[LittleFs] Mount failed with error %d\n", err);
213 TRACE(
"[LittleFs] Mounted successfully\n");
234 struct lfs_info info;
235 int err = lfs_stat(&
lfs, path.c_str(), &info);
241 return lfs_remove(&
lfs, path.c_str()) == 0;
246 return lfs_rename(&
lfs, from.c_str(), to.c_str()) == 0;
252 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_RDONLY) < 0)
255 lfs_soff_t size = lfs_file_size(&
lfs, &file);
258 lfs_file_close(&
lfs, &file);
263 int bytes = lfs_file_read(&
lfs, &file, out.data(), size);
264 lfs_file_close(&
lfs, &file);
265 return (bytes >= 0) && (bytes == size);
270 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_RDONLY) < 0)
273 lfs_soff_t size = lfs_file_size(&
lfs, &file);
274 if (size < 0 || startPosition >= size)
276 lfs_file_close(&
lfs, &file);
280 if (startPosition + length > size)
281 length = size - startPosition;
283 buffer.resize(length);
284 lfs_file_seek(&
lfs, &file, startPosition, LFS_SEEK_SET);
285 int bytesRead = lfs_file_read(&
lfs, &file, buffer.data(), length);
286 lfs_file_close(&
lfs, &file);
287 return (bytesRead >= 0) && (bytesRead ==
static_cast<int>(length));
293 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) < 0)
295 int written = lfs_file_write(&
lfs, &file, data.data(), data.size());
296 int closed = lfs_file_close(&
lfs, &file);
297 return (written ==
static_cast<int>(data.size())) && (closed == 0);
306 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) < 0)
309 int written = lfs_file_write(&
lfs, &file, data, size);
310 lfs_file_close(&
lfs, &file);
312 return (written ==
static_cast<int>(size));
318 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND) < 0)
320 printf(
"[LittleFS] appendToFile: open failed for '%s'\n", path.c_str());
321 lfs_file_close(&
lfs, &file);
324 int written = lfs_file_write(&
lfs, &file, data, size);
327 printf(
"[LittleFS] appendToFile: write failed for '%s'\n", path.c_str());
328 lfs_file_close(&
lfs, &file);
331 lfs_file_close(&
lfs, &file);
332 return written == (int)size;
338 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_RDONLY) < 0)
345 while ((readBytes = lfs_file_read(&
lfs, &file, buf,
sizeof(buf))) > 0)
347 chunkCallback(buf, readBytes);
352 printf(
"[LittleFS] streamFile: read failed for '%s'\n", path.c_str());
356 lfs_file_close(&
lfs, &file);
363 if (lfs_file_open(&
lfs, &file, path.c_str(), LFS_O_RDONLY) < 0)
365 printf(
"[LittleFS] getFileSize: open failed for '%s'\n", path.c_str());
368 lfs_soff_t size = lfs_file_size(&
lfs, &file);
369 lfs_file_close(&
lfs, &file);
370 return size < 0 ? 0 : size;
380 struct lfs_info info = {};
382 if (lfs_dir_open(&
lfs, &dir, path.c_str()) < 0)
385 while (lfs_dir_read(&
lfs, &dir, &info) > 0)
387 if (strcmp(info.name,
".") == 0 || strcmp(info.name,
"..") == 0)
391 entry.
name = info.name;
392 entry.
size = info.size;
395 out.push_back(entry);
398 lfs_dir_close(&
lfs, &dir);
405 TRACE(
"[LittleFS] Creating directory '%s'\n", path.c_str());
406 if (lfs_mkdir(&
lfs, path.c_str()) < 0)
408 printf(
"[LittleFS] Failed to create directory '%s'\n", path.c_str());
411 TRACE(
"[LittleFS] Directory '%s' created successfully\n", path.c_str());
417 return lfs_remove(&
lfs, path.c_str()) == 0;
431 TRACE(
"[LittleFs] Unmounting before format\n");
439 printf(
"[LittleFs] Format successful\n");
444 printf(
"[LittleFs] Format failed\n");
450 if (!
mount())
return nullptr;
451 auto reader = std::make_unique<LittleFsFileReader>(&
lfs);
455 if (!reader->open(path))
return nullptr;
Macro-based debug trace system with optional SD file logging.
#define TRACE_INIT(MODULE_NAME)
Declare trace usage in a source file for a given module.
#define TRACE(...)
Default trace (INFO level).
uint8_t __flash_lfs_start
static int __not_in_flash_func() lfs_prog_multicore(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
static int lfs_erase_cb_flashsafe(const struct lfs_config *c, lfs_block_t block)
static void __not_in_flash_func() flash_prog_callback(void *p)
static void __not_in_flash_func() flash_erase_callback(void *p)
Flash-backed implementation of the StorageManager interface using LittleFS.
A LittleFS-based implementation of StorageManager, storing files in flash memory.
bool unmount() override
Unmount the LittleFS filesystem.
bool rename(const std::string &from, const std::string &to) override
Rename a file or directory.
bool formatStorage() override
Format the filesystem.
bool appendToFile(const std::string &path, const uint8_t *data, size_t size) override
Append data to a file.
static int lfs_erase_cb_multicore(const struct lfs_config *c, lfs_block_t block)
static int lfs_lock(const struct lfs_config *c)
bool writeFile(const std::string &path, const std::vector< uint8_t > &data) override
Write a byte vector to a file (overwrite).
uintptr_t getFlashBase() const
get Flash base address
std::unique_ptr< StorageFileReader > openReader(const std::string &path) override
open a file for streaming read line access.
static int lfs_prog_cb_multicore(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
static StaticSemaphore_t lfs_mutex_buf
static int lfs_unlock(const struct lfs_config *c)
bool streamFile(const std::string &path, std::function< void(const uint8_t *, size_t)> chunkCallback) override
Stream a file in chunks using a callback.
bool createDirectory(const std::string &path) override
Create a new directory.
bool removeDirectory(const std::string &path) override
Remove a directory.
bool remove(const std::string &path) override
Remove a file or directory.
bool isMounted() const override
Check if the filesystem is mounted.
static int lfs_prog_cb(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
LittleFsStorageManager()
Construct the manager and configure the filesystem.
bool readFileString(const std::string &path, uint32_t startPosition, uint32_t length, std::string &buffer)
Read a file string into a memory buffer.
bool mount() override
Mount the LittleFS filesystem.
static int lfs_read_cb(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size)
bool exists(const std::string &path) override
Check if a file or directory exists.
static int lfs_erase_cb_singlecore(const struct lfs_config *c, lfs_block_t block)
static int lfs_prog_cb_singlecore(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size)
bool listDirectory(const std::string &path, std::vector< FileInfo > &out) override
List files in a directory.
size_t getFileSize(const std::string &path) override
Get the size of a file.
bool readFile(const std::string &path, std::vector< uint8_t > &out) override
Read a file into a byte vector.
static SemaphoreHandle_t lfs_mutex
static int lfs_erase_cb(const struct lfs_config *c, lfs_block_t block)
Delegates to user or system configuration.
#define HTTP_BUFFER_SIZE
Size of the HTTP buffer for request/response data.
Structure representing metadata for a file or directory.
bool isDirectory
True if item is a directory.
size_t size
Size in bytes.
bool isReadOnly
True if item is read-only.
std::string name
File or directory name.
System utilities for diagnostics, memory, stack usage, and tracing.