删除FlashDB

This commit is contained in:
2026-07-21 21:48:23 +08:00
parent 66a1e8fd6a
commit d48be81478
11 changed files with 102 additions and 971 deletions

View File

@@ -4,7 +4,7 @@
## 项目概述 ## 项目概述
STM32F407ZGTx (Cortex-M4 FPU) 基础固件项目,集成 CH395F 以太网控制器 SPI 驱动、GD5F2GQ5UE SPI NAND Flash 存储(含 FlashDB KVDB/TSDB 数据库)和 TPAFE5160 16位8通道同步采样 ADC 并行接口驱动。 STM32F407ZGTx (Cortex-M4 FPU) 基础固件项目,集成 CH395F 以太网控制器 SPI 驱动、GD5F2GQ5UE SPI NAND Flash 存储(dhara FTL + FatFS 文件系统)和 TPAFE5160 16位8通道同步采样 ADC 并行接口驱动。
## 目录结构 ## 目录结构
@@ -24,17 +24,13 @@ STM32F4-Base/
│ │ │ └── net_select.c # select/poll 实现 │ │ │ └── net_select.c # select/poll 实现
│ │ ├── GD5F2GQ5UE/ # GD5F2GQ5UE NAND Flash 驱动(手写) │ │ ├── GD5F2GQ5UE/ # GD5F2GQ5UE NAND Flash 驱动(手写)
│ │ │ ├── gd5f2gq5ue.h/c # 底层 SPI 驱动 │ │ │ ├── gd5f2gq5ue.h/c # 底层 SPI 驱动
│ │ │ ── fal_flash_gd5f2gq5ue.c # FAL 设备适配层 │ │ │ ── nand_ftl.h/c # dhara FTL + FatFS diskio 适配层
│ │ │ ├── fal_cfg.h # FAL 设备表 + 分区表
│ │ │ └── fdb_cfg.h # FlashDB 功能配置
│ │ └── TPAFE5160/ # TPAFE5160 ADC 并行接口驱动(手写) │ │ └── TPAFE5160/ # TPAFE5160 ADC 并行接口驱动(手写)
│ ├── STM32F4xx_HAL_Driver/ # ST HAL 库CubeMX 生成) │ ├── STM32F4xx_HAL_Driver/ # ST HAL 库CubeMX 生成)
│ └── CMSIS/ # ARM CMSISCubeMX 生成) │ └── CMSIS/ # ARM CMSISCubeMX 生成)
├── Lib/ ├── Lib/
── FlashDB/ # FlashDB 数据库库v2.2.99 ── dhara/ # dhara FTL (Flash Translation Layer)
├── src/ # FlashDB 核心源码 └── FatFs/ # FatFs 文件系统 (v0.15)
│ ├── inc/ # FlashDB 头文件
│ └── port/fal/ # FAL 抽象层
├── MDK-ARM/ # Keil MDK 工程文件 ├── MDK-ARM/ # Keil MDK 工程文件
├── docs/ # 参考文档 ├── docs/ # 参考文档
└── STM32F407-Demo.ioc # STM32CubeMX 项目源文件 └── STM32F407-Demo.ioc # STM32CubeMX 项目源文件
@@ -49,7 +45,7 @@ STM32F4-Base/
| `Drivers/BSP/NET/net_socket.c/h` | BSD Socket API 网络抽象层 | | `Drivers/BSP/NET/net_socket.c/h` | BSD Socket API 网络抽象层 |
| `Drivers/BSP/NET/net_select.c/h` | select/poll I/O 多路复用 | | `Drivers/BSP/NET/net_select.c/h` | select/poll I/O 多路复用 |
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c/h` | GD5F2GQ5UE NAND Flash SPI 驱动 | | `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c/h` | GD5F2GQ5UE NAND Flash SPI 驱动 |
| `Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c` | FAL 设备适配层 | | `Drivers/BSP/GD5F2GQ5UE/nand_ftl.c` | dhara FTL + FatFS diskio 适配层 |
| `Drivers/BSP/TPAFE5160/tpafe5160.c/h` | TPAFE5160 ADC 并行接口驱动 | | `Drivers/BSP/TPAFE5160/tpafe5160.c/h` | TPAFE5160 ADC 并行接口驱动 |
| `Src/freertos.c` | FreeRTOS task 创建和任务函数CubeMX 生成 + 手写) | | `Src/freertos.c` | FreeRTOS task 创建和任务函数CubeMX 生成 + 手写) |
| `Inc/FreeRTOSConfig.h` | FreeRTOS 内核配置 | | `Inc/FreeRTOSConfig.h` | FreeRTOS 内核配置 |
@@ -87,7 +83,7 @@ STM32F4-Base/
``` ```
HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init() → MX_SPI2_Init() → MX_SPI1_Init() HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init() → MX_SPI2_Init() → MX_SPI1_Init()
→ gd5f2gq5ue_init() → fdb_kvdb_init() → [USER CODE: net_init + TCP listen + 其他外设初始化] → gd5f2gq5ue_init() → [USER CODE: net_init + TCP listen + 其他外设初始化]
→ osKernelInitialize() → MX_FREERTOS_Init() → osKernelStart() ← FreeRTOS 调度器启动 → osKernelInitialize() → MX_FREERTOS_Init() → osKernelStart() ← FreeRTOS 调度器启动
→ [FreeRTOS tasks: defaultTask, netTask 运行] → [FreeRTOS tasks: defaultTask, netTask 运行]
``` ```
@@ -106,12 +102,11 @@ HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
## 注意 ## 注意
- `Inc/``Src/` 中 CubeMX 生成的文件带有 `USER CODE BEGIN`/`END` 标记,自定义代码应写在这些区域之间 - `Inc/``Src/` 中 CubeMX 生成的文件带有 `USER CODE BEGIN`/`END` 标记,自定义代码应写在这些区域之间
- `ch395f.c/h``gd5f2gq5ue.c/h``fal_flash_gd5f2gq5ue.c` 为纯手工代码,不受 CubeMX 保护 - `ch395f.c/h``gd5f2gq5ue.c/h``nand_ftl.c/h` 为纯手工代码,不受 CubeMX 保护
- `tpafe5160.c/h` 为纯手工代码,不受 CubeMX 保护 - `tpafe5160.c/h` 为纯手工代码,不受 CubeMX 保护
- CH395F 每次 SPI 事务需调用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹 - CH395F 每次 SPI 事务需调用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹
- GD5F2GQ5UE 的 `gd5f2gq5ue.c` 中声明了 `extern SPI_HandleTypeDef hspi1`,需确保 SPI1 已初始化 - GD5F2GQ5UE 的 `gd5f2gq5ue.c` 中声明了 `extern SPI_HandleTypeDef hspi1`,需确保 SPI1 已初始化
- FlashDB 使用 FAL 模式,`fdb_cfg.h` 中定义 `FDB_USING_FAL_MODE``fal_cfg.h` 中定义分区表
- FlashDB 详细使用说明见 `FlashDB使用说明.md`
- `sd2506.c/h` 为纯手工代码,不受 CubeMX 保护 - `sd2506.c/h` 为纯手工代码,不受 CubeMX 保护
- FreeRTOS Kernel V10.3.1 via CMSIS-RTOS V2 接口HAL 时基使用 TIM7非 SysTick避免与 FreeRTOS 冲突) - FreeRTOS Kernel V10.3.1 via CMSIS-RTOS V2 接口HAL 时基使用 TIM7非 SysTick避免与 FreeRTOS 冲突)
- NVIC 优先级分组 4 位,外设中断优先级全部 ≥ `configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY`5确保 ISR 可调 FreeRTOS API - NVIC 优先级分组 4 位,外设中断优先级全部 ≥ `configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY`5确保 ISR 可调 FreeRTOS API
@@ -157,13 +152,10 @@ HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
| 分区名 | 偏移 | 大小 | 块范围 | 用途 | | 分区名 | 偏移 | 大小 | 块范围 | 用途 |
|--------|------|------|--------|------| |--------|------|------|--------|------|
| fdb_kvdb1 | 0 | 64MB | Block 0~511 | FlashDB KVDB 键值数据库 |
| fdb_tsdb1 | 64MB | 64MB | Block 512~1023 | FlashDB TSDB 时序数据库 |
| ftl_fatfs | 128MB | 128MB | Block 1024~2047 | dhara FTL + FatFS 文件系统 | | ftl_fatfs | 128MB | 128MB | Block 1024~2047 | dhara FTL + FatFS 文件系统 |
- FlashDB 通过 FAL 访问 `fdb_kvdb1` / `fdb_tsdb1``Drivers/BSP/GD5F2GQ5UE/fal_cfg.h` - FatFS 通过 dhara FTL 访问 `ftl_fatfs` 分区,`nand_ftl.c``FTL_START_BLOCK = FTL_FATFS_OFFSET / GD5F_BLOCK_SIZE`
- FatFS 通过 dhara FTL 访问 `ftl_fatfs` 分区,`nand_ftl.c``FTL_START_BLOCK = FTL_FATFS_OFFSET / GD5F_BLOCK_SIZE`(与 `fal_cfg.h` 联动) - Block 0~1023128MB预留可供后续扩展
- 三个分区物理隔离,互不重叠,分区配置统一在 `fal_cfg.h:25-30`
## TPAFE5160 驱动关键点 ## TPAFE5160 驱动关键点

View File

@@ -1,63 +0,0 @@
#ifndef __FAL_CFG_H
#define __FAL_CFG_H
/*
* 模块名称FAL 配置
* 模块功能:定义 Flash 物理分区布局和 FAL 设备/分区表
* 适用平台STM32F407ZGT6
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-20 王建锋 统一分区配置,添加 FTL 分区宏供 nand_ftl.c 使用
*/
#ifdef __cplusplus
extern "C" {
#endif
/* ================== 物理分区布局256MB GD5F2GQ5UE ================== */
/*
* 分区名 偏移 大小 块范围 用途
* fdb_kvdb1 0 64MB Block 0~511 FlashDB KVDB
* fdb_tsdb1 64MB 64MB Block 512~1023 FlashDB TSDB
* ftl_fatfs 128MB 128MB Block 1024~2047 dhara FTL + FatFS
*/
#define FDB_KVDB1_OFFSET 0
#define FDB_KVDB1_SIZE (64 * 1024 * 1024)
#define FDB_TSDB1_OFFSET (FDB_KVDB1_OFFSET + FDB_KVDB1_SIZE)
#define FDB_TSDB1_SIZE (64 * 1024 * 1024)
#define FTL_FATFS_OFFSET (FDB_TSDB1_OFFSET + FDB_TSDB1_SIZE)
#define FTL_FATFS_SIZE (128 * 1024 * 1024)
/* ====================== FAL 配置(需 FAL 头文件) ====================== */
#define FAL_DEBUG 0
/* 启用分区表配置FAL 库要求此宏) */
#define FAL_PART_HAS_TABLE_CFG
/* ======================== Flash 设备表 ======================== */
extern const struct fal_flash_dev g_gd5f2gq5ue_flash;
#define FAL_FLASH_DEV_TABLE \
{ \
&g_gd5f2gq5ue_flash, \
}
/* ======================== 分区表 ======================== */
#ifdef FAL_PART_HAS_TABLE_CFG
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", "gd5f2gq5ue", FDB_KVDB1_OFFSET, FDB_KVDB1_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", "gd5f2gq5ue", FDB_TSDB1_OFFSET, FDB_TSDB1_SIZE, 0}, \
}
#endif /* FAL_PART_HAS_TABLE_CFG */
#ifdef __cplusplus
}
#endif
#endif /* __FAL_CFG_H */

View File

@@ -1,69 +0,0 @@
/*
* 讓。蝮怜錐遘ー<E98198>哥AL Flash 隶セ螟<EFBDBE>€<C280>
* 讓。蝮怜粥閭ス<E996AD>壼ー<E5A3BC> GD5F2GQ5UE 鬩ア蜉ィ謗・蜿」騾る<E9A8BE><E3828B>?FAL 譯<>
* 騾ら畑蟷ウ蜿ー<E89CBF>售TM32F407ZGT6
* 菴懆€<E68786>シ夂視蟒コ<E89F92>? * 蛻帛サコ譌・譛滂ソ?026-07-16
* 菫ョ謾ケ隶ー蠖包ソ? * 2026-07-16 邇句サコ<EFBDBB>? 蛻帛サコ蛻晏ァ狗沿譛ャ
*/
/* 螟エ譁<EFBDB4>サカ蛹<EFBDB6>性蛹コ */
#include "fal_def.h"
#include "gd5f2gq5ue.h"
/* ======================== FAL 謫堺ス懷<EFBDBD>謨ー騾る<E9A8BE> ======================== */
/*
* 蜃ス謨ー蜉溯<E89C89><E6BAAF>哥lash 隶セ螟<EFBDBE><E89E9F>蟋句喧騾る<E9A8BE>
* 蜈・蜿」蜿よ焚<E38288>壽裏
* 霑泌屓蛟シ<E89B9F><EFBDBC>0 - 謌仙粥<E4BB99><EFBFBD><E6829F>?- 髞呵ッッ<EFBDAF>? * 髯仙ョ壽擅莉カ<E88E89>售PI <20>?GPIO 蟾イ逕ア CubeMX 蛻晏ァ句喧螳鯉ソ? * 蜃ス謨ー隸エ譏趣シ夊ー<E5A48A>畑蠎募アるゥア蜉ィ逧<EFBDA8><E980A7>蟋句喧蜃ス<E89C83>? */
static int gd5f_fal_init(void) {
return gd5f2gq5ue_init();
}
/*
* 蜃ス謨ー蜉溯<E89C89><E6BAAF>哥lash 隸サ蜿夜€<C280>
* 蜈・蜿」蜿よ焚<E38288>嗤ffset - 襍キ蟋句ュ苓鰍蛛冗ァサ long
* p_buf - 謨ー謐ョ郛灘<E9839B><E78198>? uint8_t*
* size - 隸サ蜿門ュ苓鰍<E88B93>? size_t
* 霑泌屓蛟シ<E89B9F><EFBDBC>0 - 謌仙粥<E4BB99><EFBFBD><E6829F>?- 髞呵ッッ<EFBDAF>? * 髯仙ョ壽擅莉カ<E88E89>喩d5f_fal_init() 蟾イ謌仙粥隹<E7B2A5>ソ? * 蜃ス謨ー隸エ譏趣シ夂峩謗・霓ャ蜿大芦蠎募アるゥア蜉ィ逧<EFBDA8>ッサ蜿門<E89CBF><E99680>? */
static int gd5f_fal_read(long offset, uint8_t *p_buf, size_t size) {
return gd5f2gq5ue_read(offset, p_buf, size);
}
/*
* 蜃ス謨ー蜉溯<E89C89><E6BAAF>哥lash 蜀吝<E89C80>騾る<E9A8BE>
* 蜈・蜿」蜿よ焚<E38288>嗤ffset - 襍キ蟋句ュ苓鰍蛛冗ァサ long
* p_buf - 謨ー謐ョ郛灘<E9839B><E78198>? const uint8_t*
* size - 蜀吝<E89C80>蟄苓鰍<E88B93>? size_t
* 霑泌屓蛟シ<E89B9F><EFBDBC>0 - 謌仙粥<E4BB99><EFBFBD><E6829F>?- 髞呵ッッ<EFBDAF>? * 髯仙ョ壽擅莉カ<E88E89>夂岼譬<E5B2BC>玄蝓溷キイ謫ヲ髯、
* 蜃ス謨ー隸エ譏趣シ夂峩謗・霓ャ蜿大芦蠎募アるゥア蜉ィ逧<EFBDA8><E980A7>蜈・蜃ス<E89C83>? */
static int gd5f_fal_write(long offset, const uint8_t *p_buf, size_t size) {
return gd5f2gq5ue_write(offset, p_buf, size);
}
/*
* 蜃ス謨ー蜉溯<E89C89><E6BAAF>哥lash 謫ヲ髯、騾る<E9A8BE>
* 蜈・蜿」蜿よ焚<E38288>嗤ffset - 襍キ蟋句ュ苓鰍蛛冗ァサ long
* size - 謫ヲ髯、蟄苓鰍<E88B93>? size_t
* 霑泌屓蛟シ<E89B9F><EFBDBC>0 - 謌仙粥<E4BB99><EFBFBD><E6829F>?- 髞呵ッッ<EFBDAF>? * 髯仙ョ壽擅莉カ<E88E89>喩d5f_fal_init() 蟾イ謌仙粥隹<E7B2A5>ソ? * 蜃ス謨ー隸エ譏趣シ夂峩謗・霓ャ蜿大芦蠎募アるゥア蜉ィ逧<EFBDA8>逃髯、蜃ス<E89C83>? */
static int gd5f_fal_erase(long offset, size_t size) {
return gd5f2gq5ue_erase(offset, size);
}
/* ======================== FAL Flash 隶セ螟<EFBDBE>ョ壻ケ<E5A3BB> ======================== */
/* GD5F2GQ5UE FAL 隶セ螟<EFBDBE>ョ樔セ具シ梧€サ螳ケ<E89EB3>?56MB<4D>悟摎螟ァ蟆<EFBDA7>128KB */
const struct fal_flash_dev g_gd5f2gq5ue_flash = {
.name = "gd5f2gq5ue",
.addr = 0,
.len = GD5F_TOTAL_SIZE,
.blk_size = GD5F_BLOCK_SIZE,
.ops = {
.init = gd5f_fal_init,
.read = gd5f_fal_read,
.write = gd5f_fal_write,
.erase = gd5f_fal_erase,
},
.write_gran = 8,
};

View File

@@ -1,40 +0,0 @@
#ifndef __FDB_CFG_H
#define __FDB_CFG_H
/*
* 模块名称FlashDB 配置
* 模块功能:配置 FlashDB 数据库功能开关和参数
* 适用平台STM32F407ZGT6
* 作者:王建锋
* 创建日期2026-07-16
* 修改记录:
* 2026-07-16 王建锋 创建初始版本
*/
#ifdef __cplusplus
extern "C" {
#endif
/* 启用 KVDB键值数据库 */
#define FDB_USING_KVDB
/* KVDB 版本号变化时自动更新到最新默认值(默认关闭) */
/* #define FDB_KV_AUTO_UPDATE */
/* 启用 TSDB时序数据库 */
#define FDB_USING_TSDB
/* 使用 FAL 存储模式(非文件模式) */
#define FDB_USING_FAL_MODE
/* Flash 写入粒度单位bitSTM32F4 字节可编程 = 8 */
#define FDB_WRITE_GRAN 8
/* 调试输出使能 */
/*#define FDB_DEBUG_ENABLE*/
#ifdef __cplusplus
}
#endif
#endif /* __FDB_CFG_H */

View File

@@ -16,8 +16,8 @@
#include "nand.h" #include "nand.h"
#include "map.h" #include "map.h"
/* 统一分区配置 */ /* FTL 分区起始地址(块 1024偏移 128MB */
#include "fal_cfg.h" #define FTL_FATFS_OFFSET (128U * 1024U * 1024U)
/* 调试输出配置 */ /* 调试输出配置 */
#define DBG_TAG "[NAND_FTL]" #define DBG_TAG "[NAND_FTL]"

Submodule Lib/FlashDB deleted from 8236571f6e

View File

@@ -340,7 +340,7 @@
<MiscControls></MiscControls> <MiscControls></MiscControls>
<Define>USE_HAL_DRIVER,STM32F407xx,NDEBUG</Define> <Define>USE_HAL_DRIVER,STM32F407xx,NDEBUG</Define>
<Undefine></Undefine> <Undefine></Undefine>
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Lib/FlashDB/port/fal/inc;../Lib/FlashDB/inc;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../App;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs</IncludePath> <IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../App;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@@ -1221,11 +1221,6 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\Drivers\BSP\CH395F\ch395f_test.c</FilePath> <FilePath>..\Drivers\BSP\CH395F\ch395f_test.c</FilePath>
</File> </File>
<File>
<FileName>fal_flash_gd5f2gq5ue.c</FileName>
<FileType>1</FileType>
<FilePath>..\Drivers\BSP\GD5F2GQ5UE\fal_flash_gd5f2gq5ue.c</FilePath>
</File>
<File> <File>
<FileName>gd5f2gq5ue.c</FileName> <FileName>gd5f2gq5ue.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -1263,46 +1258,6 @@
</File> </File>
</Files> </Files>
</Group> </Group>
<Group>
<GroupName>lib/FlashDB</GroupName>
<Files>
<File>
<FileName>fdb.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\src\fdb.c</FilePath>
</File>
<File>
<FileName>fdb_kvdb.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\src\fdb_kvdb.c</FilePath>
</File>
<File>
<FileName>fdb_tsdb.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\src\fdb_tsdb.c</FilePath>
</File>
<File>
<FileName>fdb_utils.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\src\fdb_utils.c</FilePath>
</File>
<File>
<FileName>fal.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\port\fal\src\fal.c</FilePath>
</File>
<File>
<FileName>fal_flash.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\port\fal\src\fal_flash.c</FilePath>
</File>
<File>
<FileName>fal_partition.c</FileName>
<FileType>1</FileType>
<FilePath>..\Lib\FlashDB\port\fal\src\fal_partition.c</FilePath>
</File>
</Files>
</Group>
<Group> <Group>
<GroupName>Middlewares/FreeRTOS</GroupName> <GroupName>Middlewares/FreeRTOS</GroupName>
<GroupOption> <GroupOption>

View File

@@ -3,73 +3,65 @@ Rebuild target 'STM32F407-Demo'
assembling startup_stm32f407xx.s... assembling startup_stm32f407xx.s...
compiling crc.c... compiling crc.c...
compiling ringbuf.c... compiling ringbuf.c...
compiling dma.c...
compiling stm32f4xx_hal_timebase_tim.c...
compiling stm32f4xx_it.c...
compiling spi.c...
compiling stm32f4xx_hal_flash_ramfunc.c...
compiling i2c.c... compiling i2c.c...
compiling gpio.c... compiling gpio.c...
compiling stm32f4xx_hal_msp.c...
compiling spi.c...
compiling stm32f4xx_it.c...
compiling stm32f4xx_hal_timebase_tim.c...
compiling sys_clock.c...
compiling stm32f4xx_hal_flash_ex.c...
compiling dma.c...
compiling app_main.c...
compiling stm32f4xx_hal_flash_ramfunc.c...
compiling stm32f4xx_hal_flash.c...
compiling usart.c...
compiling stm32f4xx_hal_gpio.c...
compiling stm32f4xx_hal_rcc_ex.c... compiling stm32f4xx_hal_rcc_ex.c...
compiling rs485_task.c... compiling app_main.c...
compiling stm32f4xx_hal_msp.c...
compiling stm32f4xx_hal_gpio.c...
compiling stm32f4xx_hal_flash_ex.c...
compiling stm32f4xx_hal_flash.c...
compiling sys_clock.c...
compiling usart.c...
compiling adc_task.c... compiling adc_task.c...
compiling stm32f4xx_hal_rcc.c... compiling rs485_task.c...
compiling net_task.c...
compiling freertos.c...
compiling main.c...
compiling stm32f4xx_hal_tim_ex.c... compiling stm32f4xx_hal_tim_ex.c...
compiling net_task.c...
compiling stm32f4xx_hal_rcc.c...
compiling main.c...
compiling freertos.c...
compiling stm32f4xx_hal_tim.c... compiling stm32f4xx_hal_tim.c...
compiling fdb.c... compiling croutine.c...
compiling fdb_kvdb.c... compiling event_groups.c...
compiling fdb_tsdb.c... compiling list.c...
compiling fdb_utils.c... compiling queue.c...
compiling fal.c... compiling stream_buffer.c...
compiling fal_flash.c... compiling timers.c...
compiling fal_partition.c... compiling tasks.c...
compiling heap_4.c...
compiling port.c...
compiling stm32f4xx_hal_dma_ex.c... compiling stm32f4xx_hal_dma_ex.c...
compiling stm32f4xx_hal_dma.c... compiling stm32f4xx_hal_dma.c...
compiling croutine.c...
compiling stm32f4xx_hal_pwr_ex.c...
compiling stm32f4xx_hal_i2c_ex.c...
compiling stm32f4xx_hal_pwr.c... compiling stm32f4xx_hal_pwr.c...
compiling stm32f4xx_hal.c... compiling journal.c...
compiling event_groups.c... compiling stm32f4xx_hal_pwr_ex.c...
compiling system_stm32f4xx.c... compiling map.c...
compiling stm32f4xx_hal_exti.c...
compiling stm32f4xx_hal_cortex.c... compiling stm32f4xx_hal_cortex.c...
compiling list.c... compiling stm32f4xx_hal.c...
compiling system_stm32f4xx.c...
compiling stm32f4xx_hal_i2c_ex.c...
compiling stm32f4xx_hal_exti.c...
compiling ff.c...
compiling rs485.c... compiling rs485.c...
compiling fal_flash_gd5f2gq5ue.c...
compiling tpafe5160.c... compiling tpafe5160.c...
compiling sd2506.c... compiling sd2506.c...
compiling stm32f4xx_hal_spi.c...
compiling ch395f.c...
compiling gd5f2gq5ue.c... compiling gd5f2gq5ue.c...
compiling queue.c... compiling ch395f.c...
compiling nand_ftl.c... compiling stm32f4xx_hal_spi.c...
compiling stream_buffer.c...
compiling stm32f4xx_hal_uart.c... compiling stm32f4xx_hal_uart.c...
compiling net_select.c... compiling net_select.c...
compiling nand_ftl.c...
compiling ch395f_test.c... compiling ch395f_test.c...
compiling timers.c...
compiling net_socket.c... compiling net_socket.c...
compiling heap_4.c...
compiling tasks.c...
compiling stm32f4xx_hal_i2c.c... compiling stm32f4xx_hal_i2c.c...
compiling map.c...
compiling journal.c...
compiling port.c...
compiling ff.c...
compiling cmsis_os2.c... compiling cmsis_os2.c...
linking... linking...
Program Size: Code=58900 RO-data=3560 RW-data=244 ZI-data=54796 Program Size: Code=48264 RO-data=1416 RW-data=220 ZI-data=53788
FromELF: creating hex file... FromELF: creating hex file...
".\STM32F407-Demo\STM32F407-Demo.axf" - 0 Error(s), 0 Warning(s). ".\STM32F407-Demo\STM32F407-Demo.axf" - 0 Error(s), 0 Warning(s).
Build Time Elapsed: 00:00:20 Build Time Elapsed: 00:00:16

View File

@@ -32,7 +32,6 @@
#include "net_socket.h" #include "net_socket.h"
#include "usart.h" #include "usart.h"
#include "ff.h" #include "ff.h"
#include "flashdb.h"
#include "gd5f2gq5ue.h" #include "gd5f2gq5ue.h"
/* USER CODE END Includes */ /* USER CODE END Includes */
@@ -76,7 +75,6 @@ typedef struct {
/* Private variables ---------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */ /* USER CODE BEGIN Variables */
static struct fdb_kvdb s_kvdb;
static storage_test_stats_t g_storage_stats; static storage_test_stats_t g_storage_stats;
static uint8_t s_perf_buf[4096]; static uint8_t s_perf_buf[4096];
/* USER CODE END Variables */ /* USER CODE END Variables */
@@ -173,7 +171,6 @@ void StartDefaultTask(void *argument)
static uint8_t work[FF_MAX_SS]; static uint8_t work[FF_MAX_SS];
char read_buf[64]; char read_buf[64];
const char *test_str = "Hello FatFS + dhara FTL!"; const char *test_str = "Hello FatFS + dhara FTL!";
fdb_err_t fdb_ret;
memset(&g_storage_stats, 0, sizeof(g_storage_stats)); memset(&g_storage_stats, 0, sizeof(g_storage_stats));
@@ -211,44 +208,6 @@ void StartDefaultTask(void *argument)
f_unlink("test.txt"); f_unlink("test.txt");
} }
/* ==================== FlashDB KVDB 测试 ==================== */
DBG_INFO("=== Storage Test: FlashDB KVDB ===");
/* 第一次 init会触发 FAL 初始化,报告错误但成功) */
fdb_ret = fdb_kvdb_init(&s_kvdb, "kvdb1", "fdb_kvdb1", NULL, NULL);
/* 清除旧验证数据:格式化所有 sector */
fdb_kv_set_default(&s_kvdb);
/* 重新初始化干净的数据库 */
fdb_ret = fdb_kvdb_init(&s_kvdb, "kvdb1", "fdb_kvdb1", NULL, NULL);
STORAGE_TEST_CHECK(fdb_ret == FDB_NO_ERR, "fdb_kvdb_init");
if (fdb_ret == FDB_NO_ERR) {
fdb_ret = fdb_kv_set(&s_kvdb, "hello", "FlashDB KVDB!");
STORAGE_TEST_CHECK(fdb_ret == FDB_NO_ERR, "fdb_kv_set(hello)");
char *val = fdb_kv_get(&s_kvdb, "hello");
STORAGE_TEST_CHECK(val != NULL && strcmp(val, "FlashDB KVDB!") == 0,
"fdb_kv_get(hello) -> \"%s\"", val ? val : "NULL");
uint32_t blob_data = 0xDEADBEEF;
struct fdb_blob blob;
fdb_blob_make(&blob, &blob_data, sizeof(blob_data));
fdb_ret = fdb_kv_set_blob(&s_kvdb, "counter", &blob);
STORAGE_TEST_CHECK(fdb_ret == FDB_NO_ERR, "fdb_kv_set_blob(counter)");
uint32_t read_data = 0;
struct fdb_blob read_blob;
fdb_blob_make(&read_blob, &read_data, sizeof(read_data));
size_t len = fdb_kv_get_blob(&s_kvdb, "counter", &read_blob);
STORAGE_TEST_CHECK(len == sizeof(read_data) && read_data == 0xDEADBEEF,
"fdb_kv_get_blob(counter) -> 0x%08lX", (unsigned long)read_data);
fdb_kv_del(&s_kvdb, "hello");
fdb_kv_del(&s_kvdb, "counter");
}
/* ==================== FTL + FatFS 性能测试 ==================== */ /* ==================== FTL + FatFS 性能测试 ==================== */
DBG_INFO("=== Storage Test: Performance ==="); DBG_INFO("=== Storage Test: Performance ===");

View File

@@ -1,400 +0,0 @@
# FlashDB 使用说明
## 1. 概述
本项目使用 [FlashDB](https://github.com/armink/FlashDB) 嵌入式数据库,提供两种数据库:
- **KVDB**(键值数据库):存储键值对,类似 Redis 简化版
- **TSDB**(时序数据库):存储带时间戳的日志记录,支持按时间范围查询
底层存储介质为 GD5F2GQ5UE SPI NAND Flash256MB通过 FALFlash Abstraction Layer抽象层访问。
## 2. 软件架构
```
┌─────────────────────────────────────────┐
│ 用户应用main.c
├──────────────┬──────────────────────────┤
│ fdb_kvdb │ fdb_tsdb │
│ (键值数据库) │ (时序数据库) │
├──────────────┴──────────────────────────┤
│ FlashDB 核心 │
│ Lib/FlashDB/src/ │
├─────────────────────────────────────────┤
│ FAL 抽象层 │
│ Lib/FlashDB/port/fal/src/ │
├─────────────────────────────────────────┤
│ FAL 设备适配层 │
│ fal_flash_gd5f2gq5ue.c │
├─────────────────────────────────────────┤
│ GD5F2GQ5UE SPI NAND 驱动 │
│ gd5f2gq5ue.c │
├─────────────────────────────────────────┤
│ SPI1 硬件外设 + HAL 驱动 │
└─────────────────────────────────────────┘
```
## 3. 文件清单
| 文件 | 说明 | 是否自编 |
|------|------|----------|
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h` | NAND 驱动头文件 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c` | NAND 驱动实现 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c` | FAL 设备适配 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/fal_cfg.h` | FAL 设备表 + 分区表 | 是 |
| `Drivers/BSP/GD5F2GQ5UE/fdb_cfg.h` | FlashDB 功能配置 | 是 |
| `Lib/FlashDB/src/` | FlashDB 核心源码 | 否 |
| `Lib/FlashDB/port/fal/src/` | FAL 硬件抽象框架源码 | 否 |
## 4. 硬件配置
### 4.1 Flash 芯片参数
| 参数 | 值 |
|------|-----|
| 型号 | GD5F2GQ5UEGigaDevice |
| 总容量 | 2Gbit = 256MB |
| 页大小 | 2048 字节 |
| Spare 区 | 64 字节 |
| 每块页数 | 64 页 |
| 块大小 | 128KB64 × 2048 |
| 总块数 | 2048 |
| SPI 模式 | Mode 0CPOL=0, CPHA=0 |
| SPI 时钟 | 42MHzAPB2=84MHz, 分频=2 |
| MID | 0xC8 |
| DID | 0x52 |
### 4.2 引脚连接
| 信号 | STM32 引脚 | 方向 | 说明 |
|------|-----------|------|------|
| CS# | PE0 | OUT | 片选,低有效 |
| SCLK | PB3 | OUT | SPI1 时钟 |
| MOSI | PB5 | OUT | SPI1 主出从入 |
| MISO | PB4 | IN | SPI1 主入从出 |
| WP# | PB8 | OUT | 写保护,低有效(拉高禁用) |
| HOLD# | PE1 | OUT | 保持,低有效(拉高禁用) |
### 4.3 GPIO 初始化
CubeMX 中需确保以下 GPIO 上电默认电平:
- **CS#** (PE0):上电输出 **高电平**(未选中)
- **HOLD#** (PE1):上电输出 **高电平**(不保持)
- **WP#** (PB8):上电输出 **高电平**(不禁用写保护)
> 若 GPIO 初始电平错误SPI 通信将完全无响应。
## 5. 分区规划
| 分区名 | 设备 | 偏移 | 大小 | 用途 |
|--------|------|------|------|------|
| fdb_kvdb1 | gd5f2gq5ue | 0 | 64MB | KVDB 键值数据库 |
| fdb_tsdb1 | gd5f2gq5ue | 64MB | 64MB | TSDB 时序数据库 |
| (未分配) | - | 128MB | 128MB | 剩余空间 |
共使用 128MB / 256MB剩余 128MB 可扩展。
## 6. 初始化流程
```
1. HAL_Init()
2. SystemClock_Config()
3. MX_GPIO_Init() ← CS#/HOLD#/WP# 初始电平
4. MX_USART1_UART_Init() ← 调试串口
5. MX_SPI2_Init() ← CH395F 以太网
6. MX_SPI1_Init() ← GD5F2GQ5UE NAND
7. gd5f2gq5ue_init() ← NAND 初始化
8. fdb_kvdb_init() ← FlashDB KVDB 初始化
```
### 6.1 gd5f2gq5ue_init() 内部步骤
```
1. CS#/WP#/HOLD# 拉高
2. 发送复位命令FFh等待 5ms
3. 读取芯片 ID9Fh校验 MID=0xC8, DID=0x52
4. 使能内部 ECCSET_FEATURE(B0h, 10h)
5. 解除块保护SET_FEATURE(A0h, 00h)
```
> **关键点**SET_FEATURE 命令前必须先发写使能06h否则设置不生效。
## 7. KVDB 使用方法
### 7.1 初始化
```c
#include "flashdb.h"
static struct fdb_kvdb kvdb;
/* path 参数对应分区表中的分区名 "fdb_kvdb1" */
/* default_kv 传 NULL 表示不使用默认键值 */
int ret = fdb_kvdb_init(&kvdb, "db", "fdb_kvdb1", NULL, NULL);
if (ret != FDB_NO_ERR) {
/* 初始化失败处理 */
}
```
### 7.2 字符串读写
```c
/* 写入字符串 */
fdb_kv_set(&kvdb, "device_name", "STM32F407-DTU");
/* 读取字符串(返回内部缓存指针,下次写入同一 key 后失效) */
char *val = fdb_kv_get(&kvdb, "device_name");
if (val) {
printf("device_name = %s\n", val);
}
```
### 7.3 二进制数据读写Blob
```c
#include <string.h>
/* 写入二进制数据 */
uint32_t temp = 2560;
fdb_kv_set_blob(&kvdb, "temperature",
fdb_blob_make(NULL, &temp, sizeof(temp)));
/* 读取二进制数据 */
uint32_t read_temp = 0;
fdb_kv_get_blob(&kvdb, "temperature",
fdb_blob_make(NULL, &read_temp, sizeof(read_temp)));
printf("temperature = %u\n", read_temp);
```
### 7.4 删除键
```c
fdb_kv_del(&kvdb, "device_name");
```
### 7.5 遍历所有键
```c
struct fdb_kv kv;
struct fdb_kv_iterator itr;
fdb_kv_iterator_init(&kvdb, &itr);
while (fdb_kv_iterate(&kvdb, &itr)) {
kv = itr.curr;
printf("key: %s\n", kv.name);
}
```
### 7.6 打印所有键值
```c
fdb_kv_print(&kvdb);
```
## 8. TSDB 使用方法
### 8.1 获取时间戳
FlashDB 需要用户提供时间戳获取函数。本项目使用 HAL_GetTick()(毫秒):
```c
static fdb_time_t get_time(void)
{
return (fdb_time_t)HAL_GetTick();
}
```
### 8.2 初始化
```c
static struct fdb_tsdb tsdb;
/* max_len 参数限制单条记录最大长度 */
int ret = fdb_tsdb_init(&tsdb, "tsdb", "fdb_tsdb1",
get_time, 256, NULL);
```
### 8.3 追加记录
```c
/* 写入二进制数据,自动附加当前时间戳 */
uint32_t sensor_val = 3200;
fdb_tsl_append(&tsdb,
fdb_blob_make(NULL, &sensor_val, sizeof(sensor_val)));
```
### 8.4 遍历记录
```c
/* 正序遍历 */
fdb_tsl_iter(&tsdb, tsl_cb_func, NULL);
/* 逆序遍历 */
fdb_tsl_iter_reverse(&tsdb, tsl_cb_func, NULL);
/* 按时间范围遍历 */
fdb_tsl_iter_by_time(&tsdb, from_time, to_time, tsl_cb_func, NULL);
```
回调函数原型:
```c
static void tsl_cb_func(struct fdb_tsl *tsl, void *arg)
{
struct fdb_blob blob;
uint32_t val;
/* 读取数据 */
fdb_blob_read((fdb_db_t)&tsl,
fdb_tsl_to_blob(tsl, fdb_blob_make(&blob, &val, sizeof(val))));
printf("ts=%lu, val=%lu\n", tsl->time, val);
}
```
### 8.5 查询记录数量
```c
size_t count = fdb_tsl_query_count(&tsdb, from_time, to_time,
FDB_TSL_STATUS_APPEND);
```
### 8.6 清理所有记录
```c
fdb_tsl_clean(&tsdb);
```
## 9. 配置文件说明
### 9.1 fdb_cfg.h
| 宏 | 说明 |
|----|------|
| `FDB_USING_KVDB` | 启用 KVDB |
| `FDB_USING_TSDB` | 启用 TSDB |
| `FDB_USING_FAL_MODE` | 使用 FAL 模式(非文件系统) |
| `FDB_WRITE_GRAN` | 写入粒度 8字节可编程 |
| `FDB_DEBUG_ENABLE` | 启用调试输出 |
| `FDB_KV_AUTO_UPDATE` | KVDB 版本变化时自动更新(默认关闭) |
### 9.2 fal_cfg.h
分区表定义,修改分区大小需同时调整偏移和大小:
```c
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", "gd5f2gq5ue", 0, 64*1024*1024, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", "gd5f2gq5ue", 64*1024*1024, 64*1024*1024, 0}, \
}
```
字段顺序:`{魔数, 分区名, 设备名, 偏移, 大小, 标志}`
## 10. Keil 工程配置
### 10.1 头文件搜索路径
在 Keil 工程 Options → C/C++ → Include Paths 中添加:
```
../Drivers/BSP/GD5F2GQ5UE
../Lib/FlashDB/inc
../Lib/FlashDB/port/fal/inc
```
### 10.2 编译的源文件
需在 Keil 工程中添加以下源文件:
```
Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c
Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c
Lib/FlashDB/src/fdb.c
Lib/FlashDB/src/fdb_kvdb.c
Lib/FlashDB/src/fdb_tsdb.c
Lib/FlashDB/src/fdb_utils.c
Lib/FlashDB/port/fal/src/fal.c
Lib/FlashDB/port/fal/src/fal_flash.c
Lib/FlashDB/port/fal/src/fal_partition.c
```
### 10.3 全局宏定义
确保工程中定义了:
```
USE_HAL_DRIVER, STM32F407xx
```
## 11. 注意事项
### 11.1 NAND Flash 特性
1. **写前必须擦除**NAND 只能将 1→0不能 0→1。写入前目标块必须先擦除全部变为 0xFF
2. **擦除单位是块**:最小擦除单位 128KB不能按页擦除
3. **写入单位是页**单次写入不超过一页2048 字节),跨页需驱动层拆分
4. **Spare 区不可直接访问**:驱动已使能内部 ECCSpare 区由芯片硬件管理
### 11.2 驱动层注意事项
1. **每次 SPI 事务前**:必须 `CS_LOW()` 拉低片选
2. **每次 SPI 事务后**:必须 `CS_HIGH()` 拉高片选
3. **SET_FEATURE 前必须写使能**:先发 06h再发 1Fh + 地址 + 数据
4. **块擦除地址是字节地址**D8h 命令的参数 = 块编号 × 128KB不是块编号本身
5. **读取 ID 需跳过 dummy 字节**9Fh 返回 3 字节,第 0 字节无意义,第 1 字节 MID第 2 字节 DID
### 11.3 FlashDB 使用注意事项
1. **fdb_kv_get 返回值是内部缓存**:下次对同一 key 写入后,之前返回的指针失效
2. **TSDB 需要用户提供时间戳**:通过 `get_time` 回调,本项目使用 `HAL_GetTick()`
3. **fdb_kvdb_init 的 path 参数**:对应分区表中的分区名 `"fdb_kvdb1"`
4. **FlashDB 开启 FDB_DEBUG_ENABLE 后**:会通过 `fdb_print()` 输出调试信息,需确保有可用的输出(如 printf 重定向到串口)
5. **分区大小修改后**:需同步更新 `fal_cfg.h` 中的偏移和大小
### 11.4 常见问题
| 现象 | 可能原因 | 解决方法 |
|------|----------|----------|
| init 返回 -6 (ID_MISMATCH) | SPI 通信失败或芯片未上电 | 检查接线、GPIO 初始电平、虚焊 |
| KVDB init 失败 | 分区名不匹配 | 确认 `fdb_kvdb_init` 的 path 与 `fal_cfg.h` 一致 |
| 写入后读取为空 | 未擦除或写入失败 | 检查写入返回值,确认目标块已擦除 |
| 读取数据异常 | ECC 错误 | 检查 `gd5f2gq5ue_init` 是否成功使能 ECC |
| SET_FEATURE 未生效 | 缺少写使能命令 | 确认 `gd5f_set_feature` 中先调用 `gd5f_write_enable()` |
## 12. 调试方法
### 12.1 串口调试输出
FlashDB 调试输出通过 `fdb_print` 宏实现。在 `fdb_cfg.h` 中定义 `FDB_DEBUG_ENABLE`FlashDB 内部操作会自动输出到标准输出。
确保 Keil 工程中 `printf` 已重定向到 USART1PA9/PA10, 115200bps
### 12.2 NAND 驱动调试
可通过串口输出以下信息验证驱动工作正常:
```c
/* 读取芯片 ID */
uint8_t mid, did;
gd5f2gq5ue_read_id(&mid, &did);
printf("MID=0x%02X DID=0x%02X\n", mid, did);
/* 预期输出MID=0xC8 DID=0x52 */
/* 初始化测试 */
int ret = gd5f2gq5ue_init();
printf("init ret=%d\n", ret);
/* 预期输出init ret=0 */
```
### 12.3 FAL 设备注册验证
```c
#include "fal.h"
/* 检查 FAL 是否初始化成功 */
int ret = fal_init();
printf("fal_init ret=%d\n", ret);
/* 预期输出fal_init ret=0 */
```

View File

@@ -2,23 +2,19 @@
## 1. 概述 ## 1. 概述
本项目在 GD5F2GQ5UE SPI NAND Flash256MB上实现了层存储软件栈: 项目在 GD5F2GQ5UE SPI NAND Flash256MB上实现了层存储软件栈:
``` ```
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ 应用程序 (main, freertos) │ │ 应用程序 (main, freertos) │
├──────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────────┤
FlashDB KVDB FlashDB TSDB FatFs │ FatFs (文件系统)
(键值数据库) (时序数据库) (文件系统)
│ │ │ │ ├─────────────────────────────────────────────────────────────┤
├──────────┬───────────┴──────┬───────────┴──────────────────┤ │ dhara FTL │
│ │ (地址映射 · 磨损均衡 · 坏块管理 · 垃圾回收)
│ FAL 抽象层 (分区访问) │ dhara FTL │ ├─────────────────────────────────────────────────────────────┤
│ (Flash Abstraction Layer)│ (地址映射 · 磨损均衡 │
│ 直接转发到底层驱动) │ 坏块管理 · 垃圾回收) │
│ │ │ │
├──────────┴──────────────────┴──────────────────────────────┤
│ GD5F2GQ5UE NAND Flash 驱动 (底层 SPI) │ │ GD5F2GQ5UE NAND Flash 驱动 (底层 SPI) │
│ 硬件 SPI · 页读写 · 块擦除 · BBT · 内部 ECC 使能 │ │ 硬件 SPI · 页读写 · 块擦除 · BBT · 内部 ECC 使能 │
├─────────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────────┤
@@ -32,20 +28,17 @@
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ 物理分区布局 (256MB) │ │ 物理分区布局 (256MB) │
│ │ │ │
│ ┌──────────────────────┬──────────────────┬───────────────┐ │ │ ┌─────────────────────────────────────┬───────────────────┐ │
│ │ fdb_kvdb1 (64MB) │ fdb_tsdb1 (64MB) │ ftl_fatfs │ │ │ │ 预留 (128MB) │ ftl_fatfs (128MB) │ │
│ │ Block 0~511 │ Block 512~1023 │ Block 1024~2047│ │ │ │ Block 0~1023 │ Block 1024~2047 │ │
│ │ FlashDB 键值数据库 │ FlashDB 时序数据库│ dhara + FatFS │ │ │ │ 未使用 │ dhara FTL + FatFS │ │
│ └──────────────────────┴──────────────────┴───────────────┘ │ │ └─────────────────────────────────────┴───────────────────┘ │
│ 偏移: 0 64MB 128MB 256MB│ │ 偏移: 0 128MB 256MB
└─────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────┘
``` ```
**两条独立路径:** **数据路径:**
- **FlashDB 路径**`FlashDB → FAL → gd5f2gq5ue 驱动`FAL 是薄封装层,将 FAL 读写请求直接转发给底层 NAND 驱动。FlashDB 在 FAL 之上自行管理磨损均衡和掉电安全 - **应用** → `FatFS``dhara FTL``gd5f2gq5ue 驱动`。FTL 提供 LBA 到物理页的映射、磨损均衡、坏块管理和垃圾回收FatFS 通过标准 `disk_*` 接口访问 FTL 提供的块设备
- **FatFS 路径**`FatFS → dhara FTL → gd5f2gq5ue 驱动`FTL 提供 LBA 到物理页的映射、磨损均衡、垃圾回收和坏块管理FatFS 通过标准 `disk_*` 接口访问 FTL 提供的块设备。
两个路径共享最底层 NAND 驱动但各自管理不同的物理分区FlashDB 管理 Block 0~1023FTL 管理 Block 1024~2047互不干扰。
**初始化顺序:** **初始化顺序:**
``` ```
@@ -53,11 +46,8 @@ HAL_Init → SystemClock_Config → MX_GPIO_Init → MX_USART1_UART_Init
→ MX_SPI2_Init → MX_SPI1_Init → MX_SPI2_Init → MX_SPI1_Init
→ gd5f2gq5ue_init() // NAND 底层驱动 (含 BBT 扫描 + ECC 使能) → gd5f2gq5ue_init() // NAND 底层驱动 (含 BBT 扫描 + ECC 使能)
→ app_main_init() // 应用层初始化 → app_main_init() // 应用层初始化
├─ FlashDB: fdb_kvdb_init() // KVDB (可选)
├─ FlashDB: fdb_tsdb_init() // TSDB (可选)
└─ f_mount() // 触发 FTL 初始化和 FatFS 挂载
→ osKernelStart() // FreeRTOS 启动 → osKernelStart() // FreeRTOS 启动
├─ defaultTask → 存储测试 + 业务 ├─ defaultTask → f_mount() → 存储测试 + 业务
├─ netTask → 网络协议栈轮询 ├─ netTask → 网络协议栈轮询
├─ adcTask → ADC 采集 ├─ adcTask → ADC 采集
└─ rs485Task → RS485 通信 └─ rs485Task → RS485 通信
@@ -98,14 +88,10 @@ HAL_Init → SystemClock_Config → MX_GPIO_Init → MX_USART1_UART_Init
## 3. 分区布局 ## 3. 分区布局
个分区物理隔离、互不重叠,配置集中`Drivers/BSP/GD5F2GQ5UE/fal_cfg.h:18-30` 个分区,配置在 `Drivers/BSP/GD5F2GQ5UE/nand_ftl.c`
```c ```c
#define FDB_KVDB1_OFFSET 0 #define FTL_FATFS_OFFSET (128U * 1024U * 1024U) // 128MB
#define FDB_KVDB1_SIZE (64 * 1024 * 1024) // 64MB
#define FDB_TSDB1_OFFSET (FDB_KVDB1_OFFSET + FDB_KVDB1_SIZE)
#define FDB_TSDB1_SIZE (64 * 1024 * 1024) // 64MB
#define FTL_FATFS_OFFSET (FDB_TSDB1_OFFSET + FDB_TSDB1_SIZE) // 128MB
#define FTL_FATFS_SIZE (128 * 1024 * 1024) // 128MB #define FTL_FATFS_SIZE (128 * 1024 * 1024) // 128MB
``` ```
@@ -113,19 +99,15 @@ HAL_Init → SystemClock_Config → MX_GPIO_Init → MX_USART1_UART_Init
| 分区名 | 偏移 | 大小 | 物理块范围 | 逻辑用途 | | 分区名 | 偏移 | 大小 | 物理块范围 | 逻辑用途 |
|--------|------|------|-----------|----------| |--------|------|------|-----------|----------|
| `fdb_kvdb1` | 0 | 64 MB | Block 0~511 | FlashDB 键值数据库 (KVDB) | | 预留 | 0 | 128 MB | Block 0~1023 | 未使用 |
| `fdb_tsdb1` | 64 MB | 64 MB | Block 512~1023 | FlashDB 时序数据库 (TSDB) |
| `ftl_fatfs` | 128 MB | 128 MB | Block 1024~2047 | dhara FTL + FatFS | | `ftl_fatfs` | 128 MB | 128 MB | Block 1024~2047 | dhara FTL + FatFS |
### 3.2 配置联动 ### 3.2 配置联动
所有分区边界在 `fal_cfg.h` 定义后,自动传播到各子模块: - **FTL** — `nand_ftl.c``FTL_START_BLOCK = FTL_FATFS_OFFSET / GD5F_BLOCK_SIZE = 1024``FTL_NUM_BLOCKS` 自动适配剩余块数
- **FAL 分区表** — `FAL_PART_TABLE` 宏直接引用 `FDB_KVDB1_OFFSET/SIZE``FDB_TSDB1_OFFSET/SIZE`
- **FTL** — `nand_ftl.c:29` 通过 `#define FTL_START_BLOCK (FTL_FATFS_OFFSET / GD5F_BLOCK_SIZE)` 自动计算起始块号(当前 = 1024`FTL_NUM_BLOCKS` 自动适配剩余块数
- **FatFS** — 通过 `disk_ioctl(GET_SECTOR_COUNT)` 获取 FTL 管理的扇区数 - **FatFS** — 通过 `disk_ioctl(GET_SECTOR_COUNT)` 获取 FTL 管理的扇区数
> 调整分区大小时只需修改 `fal_cfg.h` 顶部 6 个宏,所有下游模块自动适配。 > 调整分区大小时只需修改 `nand_ftl.c` 中的 `FTL_FATFS_OFFSET` 宏,下游模块自动适配。
--- ---
@@ -237,94 +219,9 @@ DMA 消除了轮询模式下 SPI 状态寄存器查检的逐字节 CPU 开销,
--- ---
## 5. FAL 抽象层 ## 5. dhara FTL (Flash Translation Layer)
FAL (Flash Abstraction Layer) 是 FlashDB 自带的 flash 抽象层,**仅 FlashDB 路径使用**。它是一个薄封装层,将 FAL 的 read/write/erase 请求直接转发给底层 NAND 驱动,不做地址映射或磨损均衡(这些由 FlashDB 自身在 FAL 之上完成)。 ### 5.1 概述
FAL 不参与 FatFS/FTL 路径。FTL 有自己的 HAL 回调直接对接底层 NAND 驱动,与 FAL 无关。
```
FlashDB ──→ FAL ──→ gd5f2gq5ue_read/write/erase (直接透传)
FatFs ──→ dhara FTL ──→ dhara_nand_* 回调 ──→ gd5f2gq5ue_* (独立路径)
```
### 5.1 设备注册 (fal_flash_gd5f2gq5ue.c)
```c
const struct fal_flash_dev g_gd5f2gq5ue_flash = {
.name = "gd5f2gq5ue",
.addr = 0,
.len = GD5F_TOTAL_SIZE, // 256MB
.blk_size = GD5F_BLOCK_SIZE, // 128KB
.ops = { .init, .read, .write, .erase },
.write_gran = 8, // byte programmable
};
```
### 5.2 分区表 (fal_cfg.h)
```c
#define FAL_PART_TABLE \
{ \
{FAL_PART_MAGIC_WORD, "fdb_kvdb1", "gd5f2gq5ue", FDB_KVDB1_OFFSET, FDB_KVDB1_SIZE, 0}, \
{FAL_PART_MAGIC_WORD, "fdb_tsdb1", "gd5f2gq5ue", FDB_TSDB1_OFFSET, FDB_TSDB1_SIZE, 0}, \
}
```
FlashDB 通过分区名 (`"fdb_kvdb1"`, `"fdb_tsdb1"`) 绑定到 FAL 分区。
---
## 6. FlashDB 数据库
### 6.1 配置 (fdb_cfg.h)
```c
#define FDB_USING_KVDB // 启用键值数据库
#define FDB_USING_TSDB // 启用时序数据库
#define FDB_USING_FAL_MODE // 使用 FAL 存储模式
#define FDB_WRITE_GRAN 8 // 写粒度 8bit (字节可编程)
```
### 6.2 查询接口
FlashDB 通过 FAL 分区名查找对应的分区设备,无需 FlashDB 驱动额外的设备注册。
#### 已知 Bug 修复:状态读取偏移
**问题**`Lib/FlashDB/src/fdb_utils.c``_fdb_get_status()` 函数曾有一处错误的 off-by-one 修复(在第 130-139 行额外多减了一次 `status_num`),导致:
- 循环少检查最高状态位(只查 `byte[1,0]` 而非 `byte[2,1,0]`
- `EMPTY`(状态 1被错误地读成 `USING`(状态 2
- 所有空扇区触发 KV 遍历,在全 `0xFF` 区域发现 `len=0xFFFFFFFF`,产生 `"The KV @0xXXXX0014 length has an error"` 报错
**修复**2026-07-21 移除 `_fdb_get_status()` 中多余的 `status_num--`,恢复原始正确的循环边界。详见 `Lib/FlashDB/src/fdb_utils.c:126-144`
### 6.3 KVDB 键值数据库
适用于存储配置参数、运行状态等少量键值对。
**特点:**
- 掉电安全 (写操作带 CRC 校验)
- 支持 blob (二进制数据块)
- 自动磨损均衡
- 支持默认值 (首次启动自动写入)
- 支持 select/poll I/O 多路复用(`net_select.c`
### 6.4 TSDB 时序数据库
适用于存储采样数据、日志记录等时间序列数据。
**特点:**
- 固定长度记录
- 时间戳索引 (需提供 `get_time` 回调)
- 自动擦除 (新数据覆盖最旧数据)
- 支持按时间范围查询
---
## 7. dhara FTL (Flash Translation Layer)
### 7.1 概述
FTL 是 NAND Flash 上方最重要的组件,功能包括: FTL 是 NAND Flash 上方最重要的组件,功能包括:
@@ -336,7 +233,7 @@ FTL 是 NAND Flash 上方最重要的组件,功能包括:
| **坏块管理** | 擦除/编程失败时自动跳过并标记坏块 | | **坏块管理** | 擦除/编程失败时自动跳过并标记坏块 |
| **ECC 处理** | 检测和上报硬件 ECC 不可纠正错误 | | **ECC 处理** | 检测和上报硬件 ECC 不可纠正错误 |
### 7.2 数据结构 ### 5.2 数据结构
```c ```c
struct dhara_nand { struct dhara_nand {
@@ -350,7 +247,7 @@ struct dhara_map {
}; };
``` ```
### 7.3 NAND HAL (nand_ftl.c) ### 5.3 NAND HAL (nand_ftl.c)
dhara 通过 7 个回调函数访问物理 NAND dhara 通过 7 个回调函数访问物理 NAND
@@ -366,7 +263,7 @@ dhara 通过 7 个回调函数访问物理 NAND
所有回调自动将 dhara 逻辑块/页加 `FTL_START_BLOCK` 偏移转换为物理地址。 所有回调自动将 dhara 逻辑块/页加 `FTL_START_BLOCK` 偏移转换为物理地址。
### 7.4 初始化流程 (disk_initialize) ### 5.4 初始化流程 (disk_initialize)
``` ```
1. 设置 nand 参数 (log2_page_size=11, log2_ppb=6, num_blocks=1024) 1. 设置 nand 参数 (log2_page_size=11, log2_ppb=6, num_blocks=1024)
@@ -379,7 +276,7 @@ dhara 通过 7 个回调函数访问物理 NAND
4. 页面缓存初始化 (s_cache_buf, s_cached_lpn, s_cache_dirty) 4. 页面缓存初始化 (s_cache_buf, s_cached_lpn, s_cache_dirty)
``` ```
### 7.5 页面缓存策略 ### 5.5 页面缓存策略
FTL 之上还有一个 **单页写回缓存 (write-back cache)** FTL 之上还有一个 **单页写回缓存 (write-back cache)**
@@ -391,9 +288,9 @@ FTL 之上还有一个 **单页写回缓存 (write-back cache)**
--- ---
## 8. FatFS 集成 ## 6. FatFS 集成
### 8.1 配置 (ffconf.h) ### 6.1 配置 (ffconf.h)
```c ```c
#define FF_FS_READONLY 0 // 读写模式 #define FF_FS_READONLY 0 // 读写模式
@@ -405,7 +302,7 @@ FTL 之上还有一个 **单页写回缓存 (write-back cache)**
#define FF_FS_NORTC 1 // 无 RTC (固定时间戳) #define FF_FS_NORTC 1 // 无 RTC (固定时间戳)
``` ```
### 8.2 disk I/O 接口 ### 6.2 disk I/O 接口
| 函数 | 功能 | 关键实现 | | 函数 | 功能 | 关键实现 |
|------|------|----------| |------|------|----------|
@@ -415,7 +312,7 @@ FTL 之上还有一个 **单页写回缓存 (write-back cache)**
| `disk_write` | 写扇区 | 通过 FTL 映射写 (缓存优化) | | `disk_write` | 写扇区 | 通过 FTL 映射写 (缓存优化) |
| `disk_ioctl` | 控制命令 | GET_SECTOR_COUNT/SIZE/BLOCK_SIZE + CTRL_SYNC | | `disk_ioctl` | 控制命令 | GET_SECTOR_COUNT/SIZE/BLOCK_SIZE + CTRL_SYNC |
### 8.3 容量计算 ### 6.3 容量计算
``` ```
FTL 管理块数 = 1024 (Block 1024~2047) FTL 管理块数 = 1024 (Block 1024~2047)
@@ -428,9 +325,9 @@ FTL 开销后 ≈ 93 MB (随 GC 和 journal 使用量波动)
--- ---
## 9. 完整数据流 ## 7. 完整数据流
### 9.1 写文件流程 ### 7.1 写文件流程
``` ```
f_write("hello.txt") f_write("hello.txt")
@@ -450,7 +347,7 @@ f_close → disk_ioctl(CTRL_SYNC)
└─ 写 journal 到 NAND (持久化映射表) └─ 写 journal 到 NAND (持久化映射表)
``` ```
### 9.2 f_mkfs 格式化流程 ### 7.2 f_mkfs 格式化流程
``` ```
f_mkfs("", &opts, work, size) f_mkfs("", &opts, work, size)
@@ -463,9 +360,9 @@ f_mkfs("", &opts, work, size)
--- ---
## 10. API 参考 ## 8. API 参考
### 10.1 底层 NAND 驱动 (gd5f2gq5ue.h) ### 8.1 底层 NAND 驱动 (gd5f2gq5ue.h)
| 函数 | 说明 | | 函数 | 说明 |
|------|------| |------|------|
@@ -495,31 +392,7 @@ f_mkfs("", &opts, work, size)
| `gd5f_block_erase(block_addr)` | 块擦除 (D8h) | | `gd5f_block_erase(block_addr)` | 块擦除 (D8h) |
| `gd5f_check_ecc()` | 检查 ECC 状态位 | | `gd5f_check_ecc()` | 检查 ECC 状态位 |
### 10.2 FAL 接口 (via fal_flash_gd5f2gq5ue.c) ### 8.2 FTL/FatFS (via nand_ftl.c / ff.h)
| 函数 | 说明 |
|------|------|
| `g_gd5f2gq5ue_flash` | FAL 设备实例 |
| `fal_flash_device_find("gd5f2gq5ue")` | 查找 Flash 设备 |
| `fal_partition_find("fdb_kvdb1")` | 查找分区 |
| `fal_partition_read/write/erase` | 分区读写擦除 |
### 10.3 FlashDB (via FlashDB 库)
| 函数 | 说明 |
|------|------|
| `fdb_kvdb_init(&db, "kvdb1", "fdb_kvdb1", NULL, NULL)` | 初始化 KVDB |
| `fdb_kv_set(&db, "key", "value")` | 写键值 (字符串) |
| `fdb_kv_get(&db, "key")` | 读键值 (返回 char*) |
| `fdb_kv_del(&db, "key")` | 删除键值 |
| `fdb_kv_set_blob(&db, "key", &blob)` | 写二进制 blob |
| `fdb_kv_get_blob(&db, "key", &blob)` | 读二进制 blob |
| `fdb_kv_set_default(&db)` | 格式化所有 sector 并写入默认值 |
| `fdb_tsdb_init(&db, "tsdb1", "fdb_tsdb1", get_time, 1024, NULL)` | 初始化 TSDB |
| `fdb_tsl_append(&db, data)` | 追加时序记录 |
| `fdb_tsl_iter_by_time(&db, from, to, cb, cb_arg)` | 时间范围查询 |
### 10.4 FTL/FatFS (via nand_ftl.c / ff.h)
| 函数 | 说明 | | 函数 | 说明 |
|------|------| |------|------|
@@ -532,75 +405,9 @@ f_mkfs("", &opts, work, size)
--- ---
## 11. 使用示例 ## 9. 使用示例
### 11.1 KVDB 初始化与使用 ### 9.1 FatFS 文件操作
```c
#include "flashdb.h"
#include "fdb_cfg.h"
/* KVDB 实例 */
static struct fdb_kvdb g_kvdb;
static int kvdb_init(void) {
fdb_err_t ret = fdb_kvdb_init(&g_kvdb, "kvdb1", "fdb_kvdb1", NULL, NULL);
return (ret == FDB_NO_ERR) ? 0 : -1;
}
static void kvdb_example(void) {
/* 写字符串 */
fdb_kv_set(&g_kvdb, "device_id", "STM32F407-001");
/* 读字符串 */
const char *val = fdb_kv_get(&g_kvdb, "device_id");
/* 写二进制 blob */
struct fdb_blob blob;
uint32_t value = 42;
fdb_blob_make(&blob, &value, sizeof(value));
fdb_kv_set_blob(&g_kvdb, "counter", &blob);
/* 读二进制 blob */
uint32_t read_val;
fdb_blob_make(&blob, &read_val, sizeof(read_val));
fdb_kv_get_blob(&g_kvdb, "counter", &blob);
/* 格式化(清除所有数据) */
fdb_kv_set_default(&g_kvdb);
}
```
### 11.2 TSDB 初始化与使用
```c
static struct fdb_tsdb g_tsdb;
static time_t get_timestamp(void) {
return sys_clock_now(); // 从 RTC 获取 Unix 时间戳
}
static int tsdb_init(void) {
fdb_err_t ret = fdb_tsdb_init(&g_tsdb, "tsdb1", "fdb_tsdb1",
get_timestamp, 1024, NULL);
return (ret == FDB_NO_ERR) ? 0 : -1;
}
typedef struct {
float voltage;
float current;
float temperature;
} sensor_data_t;
static void tsdb_example(void) {
sensor_data_t data = {3.3f, 0.5f, 25.6f};
struct fdb_blob blob;
fdb_blob_make(&blob, &data, sizeof(data));
fdb_tsl_append(&g_tsdb, &blob);
}
```
### 11.3 FatFS 文件操作
```c ```c
#include "ff.h" #include "ff.h"
@@ -639,7 +446,7 @@ static void fatfs_write_read(void) {
} }
``` ```
### 11.4 FTL 格式化 ### 9.2 FTL 格式化
```c ```c
#include "nand_ftl.h" #include "nand_ftl.h"
@@ -652,12 +459,11 @@ if (nand_ftl_format() == 0) {
--- ---
## 12. 注意事项 ## 10. 注意事项
1. **擦除对齐**`gd5f2gq5ue_erase()` 的 offset 和 size 必须严格按 GD5F_BLOCK_SIZE (128KB) 对齐和整数倍。 1. **擦除对齐**`gd5f2gq5ue_erase()` 的 offset 和 size 必须严格按 GD5F_BLOCK_SIZE (128KB) 对齐和整数倍。
2. **写前擦除** — NAND 不能原地覆写FTL 和 FlashDB 内部自动管理擦除,但直接调用 `gd5f2gq5ue_write()` 前必须确保目标块已擦除。 2. **写前擦除** — NAND 不能原地覆写FTL 内部自动管理擦除,但直接调用 `gd5f2gq5ue_write()` 前必须确保目标块已擦除。
3. **FTL 首个扇区**`dhara_map_init` 的第 5 个参数 (journal 页数) 影响 GC 效率,当前为 4增大可减少写入放大但占用更多内存。 3. **FTL 首个扇区**`dhara_map_init` 的第 5 个参数 (journal 页数) 影响 GC 效率,当前为 4增大可减少写入放大但占用更多内存。
4. **坏块传播** — FTL 在擦除/编程失败后自动调用 `dhara_nand_mark_bad``gd5f2gq5ue_mark_block_bad`BBT 在 RAM 中更新,下次复位后重新扫描出厂坏块并叠加运行时坏块。 4. **坏块传播** — FTL 在擦除/编程失败后自动调用 `dhara_nand_mark_bad``gd5f2gq5ue_mark_block_bad`BBT 在 RAM 中更新,下次复位后重新扫描出厂坏块并叠加运行时坏块。
5. **功耗** — 擦除操作最大耗时约 5ms (驱动超时设为 5s),页编程约 600ms (超时 1s),读写操作快。在低功耗场景需注意合理安排操作时序。 5. **功耗** — 擦除操作最大耗时约 5ms (驱动超时设为 5s),页编程约 600ms (超时 1s),读写操作快。在低功耗场景需注意合理安排操作时序。
6. **分区隔离**三个分区物理隔离FlashDB 操作不会影响 FTL 数据,反之亦然。修改分区布局时需同步更新 `fal_cfg.h` 和确认 FTL 宏自动适配。 6. **缓存一致性**单页缓存 (s_cache_buf) 仅对 FatFS 层可见,多任务读写同一文件需在应用层同步。
7. **缓存一致性** — 单页缓存 (s_cache_buf) 仅对 FatFS 层可见,多任务读写同一文件需在应用层同步。