硬汉嵌入式论坛

 找回密码
 立即注册
查看: 13|回复: 0
收起左侧

FlashStore: 极简 A/B 分区配置存储方案

[复制链接]

3

主题

4

回帖

13

积分

新手上路

积分
13
发表于 3 小时前 | 显示全部楼层 |阅读模式
本帖最后由 CacheRivulet 于 2026-7-31 02:42 编辑

FlashStore A/B Partition
A/B 双页 Flash 存储,面向小型 MCU。零依赖,无状态。

https://github.com/createskyblue/flashstore-ab-partition

选哪个?

FlashStoreFlashDBLittleFS
定位单块配置可靠存储嵌入式键值数据库嵌入式文件系统
数据模型整块二进制键值对文件
读写方式Save/Load 整块Set/Get 按 keyOpen/Read/Write
磨损均衡XOKOK
掉电保护OK双页冗余OK事务日志OK
适用配置参数,低频更新多配置项独立读写文件、日志、大块数据


资源占用(Cortex-M0 -Os 实测)
模块Flash静态 RAM
flash_store500 bytes0~20 bytes
chacha20(可选)700 bytes0~200 bytes
xxtea(可选)737 bytes0~0
flash_store 明细:Load 158B / load_page 108B / save_page 100B / Save 66B / CRC32 52B / MaxDataSize 16B。按需链接,不用就不占。



5 分钟接入
1. 复制 include/flash_store.hsrc/flash_store.c。需要加密再加 chacha20xxtea

2. 实现 3 个回调:
  1. bool my_read(void *ctx, uint32_t addr, uint8_t *out, size_t len) {
  2.     memcpy(out, (void *)(uintptr_t)addr, len); // 或 HAL 读
  3.     return true;
  4. }
  5. bool my_erase(void *ctx, uint32_t addr, size_t len) {
  6.     HAL_FLASH_ErasePage(addr); // 整页擦除
  7.     return true;
  8. }
  9. bool my_program(void *ctx, uint32_t addr, const uint8_t *data, size_t len) {
  10.     // 按 word 编程,或 memcpy(支持字节寻址的 flash)
  11.     return true;
  12. }
复制代码
3. 初始化并读写:
  1. FlashStore_IO io = {
  2.     .read = my_read, .erase = my_erase, .program = my_program,
  3. };
  4. FlashStore_Config cfg = {
  5.     .io = &io, .page_a_address = 0x0800FE00, .page_b_address = 0x0800FE80,
  6.     .page_size = 128,
  7. };
  8. FlashStore_Save(&cfg, data, len); // 写
  9. FlashStore_Load(&cfg, data, len); // 读
复制代码
需要加密?推荐 ChaCha20——RFC 8439 标准,流密码不分块不要求对齐。实测 Cortex-M0 -Os:700B Flash + ~200B 栈,0 静态 RAM。极致省资源用 XXTEA,仅混淆级别,要求 4 字节对齐且 ≥8 字节。加密在外部做:encrypt → FlashStore_Save / FlashStore_Load → decrypt



为什么不会丢数据
A 写完才写 B。 任意时刻断电,至少一份完整数据在 flash 上。
  1. Save: A 先 → B 后 Load: 读两页 → CRC 验 → 返回好的 → 顺手修坏的
复制代码
断电在…ABLoad 结果
空闲v2v2返回 v2
写 A 中途v1返回 v1,修 A
A 完成,B 前v2 (CRC=c2)v1 (CRC=c1)CRC 不同→A 新→返回 v2,修 B
写 B 中途v2返回 v2,下次修 B
两页都坏ERROR_NO_VALID_DATA
WARN_REPAIR_FAILED?修复时 erase/program 失败,正常不会发生——收到应检查硬件。



Header 结构
每页 12 字节 header + payload:

偏移字段含义
0magic (4B)0x46534142
4length (4B)payload 大小
8crc32 (4B)payload CRC32


状态码
返回值含义
OK正常
ERROR_ARGUMENT参数错误
ERROR_WRITE擦除或编程失败
ERROR_NO_VALID_DATA两页都坏了
WARN_REPAIR_FAILED数据正确但冗余修复失败


测试
  1. cmake -S . -B build && cmake --build build && ./build/flash_store_tests.exe
复制代码
10 个测试覆盖:正常读写、A 坏回退 B、B 坏从 A 修、A 写失败保 B、CRC 裁决新旧、双页全坏、MaxDataSize、Save/Load 参数校验、ConfigCheck、修复失败告警。



License
MIT




build 31 July 2026 02:38 (UTC+8)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2026-7-31 05:20 , Processed in 1.148093 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表