mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-23 11:42:25 +00:00
ditch arduino's hacky-hacky FS, back to zephyr native
mg24 fix dfu zip generation fix
This commit is contained in:
1 parent
6cb80a31af
commit
57d8cf1c46
27 files changed
+572
-175
No files matched your search
@@ -4,14 +4,14 @@
|
||||
*
|
||||
* Universal mount strategy:
|
||||
* nRF52: Manual mount /efs (ExtraFS, 100KB) + /ifs (InternalFS, 28KB)
|
||||
* with block_size=128 and custom erase for Arduino MeshCore compat.
|
||||
* using native Zephyr LittleFS (block_size=4096).
|
||||
* Others: DTS-automounted /lfs (single partition).
|
||||
* QSPI: /ext overrides contacts mount when available.
|
||||
*
|
||||
* Data format (all platforms):
|
||||
* contacts3 — 152-byte records (Arduino-compatible)
|
||||
* new_prefs — Arduino-compatible byte layout
|
||||
* channels2 — 68-byte records (identical to Arduino)
|
||||
* contacts3 — 152-byte records
|
||||
* new_prefs — byte layout
|
||||
* channels2 — 68-byte records
|
||||
* _main.id — identity blob
|
||||
* adv_blobs — fixed record array
|
||||
*/
|
||||
@@ -23,9 +23,6 @@
|
||||
#include <zephyr/device.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Custom 128B-block erase — defined in lfs_128b_erase.c */
|
||||
extern "C" int lfs_128b_erase(const struct lfs_config *c, lfs_block_t block);
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(zephcore_datastore, CONFIG_ZEPHCORE_DATASTORE_LOG_LEVEL);
|
||||
|
||||
@@ -56,27 +53,14 @@ static bool is_mounted(const char *mount_point)
|
||||
return fs_statvfs(mount_point, &stat) == 0;
|
||||
}
|
||||
|
||||
/* ── nRF52 dual-mount: ExtraFS + InternalFS (block_size=128) ───────── */
|
||||
/* ── nRF52 dual-mount: ExtraFS + InternalFS ────────────────────────── */
|
||||
|
||||
#if FIXED_PARTITION_EXISTS(extrafs_partition) && FIXED_PARTITION_EXISTS(internalfs_partition)
|
||||
#define HAS_NRF52_DUAL_MOUNT 1
|
||||
|
||||
/* Arduino-compatible LFS: block_size=128 */
|
||||
FS_LITTLEFS_DECLARE_CUSTOM_CONFIG(extrafs_data,
|
||||
4, /* alignment */
|
||||
16, /* read_size */
|
||||
16, /* prog_size */
|
||||
128, /* cache_size = block_size */
|
||||
128 /* lookahead_size */
|
||||
);
|
||||
|
||||
FS_LITTLEFS_DECLARE_CUSTOM_CONFIG(internalfs_data,
|
||||
4, /* alignment */
|
||||
16, /* read_size */
|
||||
16, /* prog_size */
|
||||
128, /* cache_size = block_size */
|
||||
128 /* lookahead_size */
|
||||
);
|
||||
/* Native Zephyr LFS — block_size derived from flash erase size (4096). */
|
||||
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(extrafs_data);
|
||||
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(internalfs_data);
|
||||
|
||||
static struct fs_mount_t extrafs_mnt = {
|
||||
.type = FS_LITTLEFS,
|
||||
@@ -94,53 +78,56 @@ static struct fs_mount_t internalfs_mnt = {
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
/* Mount a LittleFS partition, format if mount fails. Returns the mount rc. */
|
||||
static int mount_or_format(struct fs_mount_t *mnt, int partition_id)
|
||||
{
|
||||
int rc = fs_mount(mnt);
|
||||
|
||||
if (rc < 0) {
|
||||
LOG_WRN("%s: mount failed (%d) — formatting", mnt->mnt_point, rc);
|
||||
|
||||
/* A failed fs_mount may leave fs->backend set (flash_area
|
||||
* opened in littlefs_init_backend but lfs_mount failed).
|
||||
* Clear it so the retry doesn't hit -EBUSY. */
|
||||
struct fs_littlefs *fsd = (struct fs_littlefs *)mnt->fs_data;
|
||||
if (fsd->backend) {
|
||||
flash_area_close((const struct flash_area *)fsd->backend);
|
||||
fsd->backend = NULL;
|
||||
}
|
||||
|
||||
const struct flash_area *fap;
|
||||
if (flash_area_open(partition_id, &fap) == 0) {
|
||||
flash_area_flatten(fap, 0, fap->fa_size);
|
||||
flash_area_close(fap);
|
||||
}
|
||||
rc = fs_mount(mnt);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("%s: mount failed after format: %d",
|
||||
mnt->mnt_point, rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool try_mount_nrf52_dual()
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Set custom block_size and erase callback before mount.
|
||||
* The Zephyr LFS patch (0007) preserves pre-set erase callbacks. */
|
||||
extrafs_data.cfg.block_size = 128;
|
||||
extrafs_data.cfg.erase = lfs_128b_erase;
|
||||
|
||||
internalfs_data.cfg.block_size = 128;
|
||||
internalfs_data.cfg.erase = lfs_128b_erase;
|
||||
|
||||
/* Mount ExtraFS — contacts, channels, blobs */
|
||||
rc = fs_mount(&extrafs_mnt);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("ExtraFS mount failed: %d — formatting", rc);
|
||||
const struct flash_area *fap;
|
||||
if (flash_area_open(FIXED_PARTITION_ID(extrafs_partition), &fap) == 0) {
|
||||
flash_area_flatten(fap, 0, fap->fa_size);
|
||||
flash_area_close(fap);
|
||||
}
|
||||
rc = fs_mount(&extrafs_mnt);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("ExtraFS mount failed after format: %d", rc);
|
||||
return false;
|
||||
}
|
||||
if (mount_or_format(&extrafs_mnt,
|
||||
FIXED_PARTITION_ID(extrafs_partition)) < 0) {
|
||||
return false;
|
||||
}
|
||||
efs_mounted = true;
|
||||
LOG_INF("ExtraFS at /efs (100KB, 128B blocks)");
|
||||
LOG_INF("ExtraFS at /efs: blk_sz=%u blk_cnt=%u",
|
||||
extrafs_data.cfg.block_size, extrafs_data.cfg.block_count);
|
||||
|
||||
/* Mount InternalFS — prefs, identity, BLE settings */
|
||||
rc = fs_mount(&internalfs_mnt);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("InternalFS mount failed: %d — formatting", rc);
|
||||
const struct flash_area *fap;
|
||||
if (flash_area_open(FIXED_PARTITION_ID(internalfs_partition), &fap) == 0) {
|
||||
flash_area_flatten(fap, 0, fap->fa_size);
|
||||
flash_area_close(fap);
|
||||
}
|
||||
rc = fs_mount(&internalfs_mnt);
|
||||
if (rc < 0) {
|
||||
LOG_ERR("InternalFS mount failed after format: %d", rc);
|
||||
return false;
|
||||
}
|
||||
if (mount_or_format(&internalfs_mnt,
|
||||
FIXED_PARTITION_ID(internalfs_partition)) < 0) {
|
||||
return false;
|
||||
}
|
||||
ifs_mounted = true;
|
||||
LOG_INF("InternalFS at /ifs (28KB, 128B blocks)");
|
||||
LOG_INF("InternalFS at /ifs: blk_sz=%u blk_cnt=%u",
|
||||
internalfs_data.cfg.block_size, internalfs_data.cfg.block_count);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -158,7 +145,7 @@ bool ZephyrDataStore::mount()
|
||||
return true; /* already mounted */
|
||||
}
|
||||
|
||||
/* 1. Try nRF52 dual-mount (manual, block_size=128) */
|
||||
/* 1. Try nRF52 dual-mount (manual, native block_size) */
|
||||
if (try_mount_nrf52_dual()) {
|
||||
_contacts_mnt = "/efs";
|
||||
_prefs_mnt = "/ifs";
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* Zephyr DataStore - LittleFS-backed persistence with optional QSPI flash
|
||||
*
|
||||
* Universal across all platforms (nRF52, ESP32, MG24, nRF54L).
|
||||
* On nRF52, uses Arduino MeshCore-compatible dual-mount layout:
|
||||
* /efs (ExtraFS @ 0xD4000, 100KB, block_size=128) — contacts3, channels2, blobs
|
||||
* /ifs (InternalFS @ 0xED000, 28KB, block_size=128) — new_prefs, _main.id
|
||||
* On nRF52, uses dual-mount layout with native Zephyr LittleFS:
|
||||
* /efs (ExtraFS @ 0xD4000, 100KB) — contacts3, channels2, blobs
|
||||
* /ifs (InternalFS @ 0xED000, 28KB) — new_prefs, _main.id
|
||||
* On other platforms, uses DTS-automounted /lfs for everything.
|
||||
* QSPI /ext overrides contacts path when available (any platform).
|
||||
*/
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Custom LittleFS erase callback for 128-byte blocks on 4KB-erase flash.
|
||||
*
|
||||
* Arduino MeshCore uses LFS with block_size=128 on nRF52840 which has
|
||||
* 4096-byte erase granularity. The standard Zephyr erase callback calls
|
||||
* flash_area_flatten(fa, offset, 128) which fails because the flash driver
|
||||
* requires page-aligned (4096-byte) erases.
|
||||
*
|
||||
* This callback implements read-modify-erase-write:
|
||||
* 1. Read the entire 4KB page containing the 128B block
|
||||
* 2. Memset the 128B region to 0xFF (erased state)
|
||||
* 3. Hardware-erase the 4KB page
|
||||
* 4. Write back the modified page
|
||||
*/
|
||||
|
||||
#include <zephyr/storage/flash_map.h>
|
||||
#include <zephyr/drivers/flash.h>
|
||||
#include <lfs.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HW_ERASE_SIZE 4096
|
||||
|
||||
/* Static 4KB buffer for read-modify-erase-write.
|
||||
* Both ExtraFS and InternalFS mounts are serialized by the Zephyr FS mutex,
|
||||
* so this is never accessed concurrently. */
|
||||
static uint8_t page_buf[HW_ERASE_SIZE];
|
||||
|
||||
int lfs_128b_erase(const struct lfs_config *c, lfs_block_t block)
|
||||
{
|
||||
const struct flash_area *fa = (const struct flash_area *)c->context;
|
||||
int rc;
|
||||
|
||||
/* Offset of this LFS block within the flash area */
|
||||
size_t block_offset = block * c->block_size;
|
||||
|
||||
/* Align down to the 4KB page boundary (within flash area) */
|
||||
size_t page_offset = block_offset & ~((size_t)HW_ERASE_SIZE - 1);
|
||||
size_t offset_in_page = block_offset - page_offset;
|
||||
|
||||
/* 1. Read entire 4KB page */
|
||||
rc = flash_area_read(fa, page_offset, page_buf, HW_ERASE_SIZE);
|
||||
if (rc < 0) {
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
/* 2. Set the 128B block region to erased state (0xFF) */
|
||||
memset(&page_buf[offset_in_page], 0xFF, c->block_size);
|
||||
|
||||
/* 3. Hardware-erase the 4KB page */
|
||||
rc = flash_area_flatten(fa, page_offset, HW_ERASE_SIZE);
|
||||
if (rc < 0) {
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
/* 4. Write back the modified page */
|
||||
rc = flash_area_write(fa, page_offset, page_buf, HW_ERASE_SIZE);
|
||||
if (rc < 0) {
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
Reference in new issue
Block a user