@@ -6,26 +6,67 @@ MeowKeyboard CH592F 固件在 DataFlash 中的存储布局说明。
66
77- ** 基地址** :` 0x70000 ` (CH592 物理地址)
88- ** 总容量** :32KB (` 0x0000 ` ~ ` 0x7FFF ` )
9- - ** 擦除粒度** :4KB
9+ - ** 擦除粒度** :` 256B / 4KB` (按区域策略使用)
1010- ** 写入推荐** :256 字节对齐
1111
1212## 整体布局
1313
1414| 地址范围 | 大小 | 用途 |
1515| :------- | :--- | :--- |
16- | 0x0000 ~ 0x0FFF | 4KB | 配置块(整块擦写) |
16+ | 0x0000 ~ 0x0BFF | 3KB | 配置槽轮转区(3 槽 × 1KB,配置小擦写) |
17+ | 0x0C00 ~ 0x0FFF | 1KB | runtime 热数据区(4 页 × 256B,层号高频持久化) |
1718| 0x1000 ~ 0x4FFF | 16KB | 宏数据区(8 槽 × 2KB) |
1819| 0x5000 ~ 0x7DFF | 11.5KB | 预留 |
1920| 0x7E00 ~ 0x7EFF | 256B | ** BLE SNV** (蓝牙配对信息) |
2021| 0x7F00 ~ 0x7FFF | 256B | 预留 |
2122
22- > 配置块与宏区分离于不同 4KB 块;宏区前移以避开 BLE SNV,8 槽位均可安全使用 。
23+ > 当前策略: ** 宏大擦写( 4KB 块) ** 、 ** 配置小擦写(256B 页) ** 、 ** 层号独立热数据页环 ** 。
2324
2425---
2526
2627## 配置区 (0x0000 ~ 0x0FFF)
2728
28- 配置区占据首块 4KB,整块擦除和写入。
29+ 配置区采用冷热分离:
30+
31+ - ` 0x0000 ~ 0x0BFF ` :配置槽轮转区(3 槽 × 1KB)
32+ - ` 0x0C00 ~ 0x0FFF ` :runtime 热数据区(4 页 × 256B)
33+
34+ 配置槽内偏移保持不变(以下偏移为** 槽位内偏移** )。
35+
36+ ### runtime 热数据页(0x0C00 ~ 0x0FFF,当前实现)
37+
38+ runtime 区用于高频持久化状态(当前已用于 ` current_layer ` )。区域总计 ` 1KB ` ,由 ` 4 × 256B ` 页组成,按页轮转。
39+
40+ #### 单页结构 ` kbd_runtime_page_t ` (256B)
41+
42+ | 字节 | 偏移 | 字段 | 类型 | 说明 |
43+ | :--- | :--- | :--- | :--- | :--- |
44+ | 0-3 | 0x00 | magic | uint32_t | ` 0x52554E54 ` (` \"RUNT\" ` ) |
45+ | 4-5 | 0x04 | version | uint16_t | ` 0x0001 ` |
46+ | 6-7 | 0x06 | flags | uint16_t | 预留,当前写 ` 0 ` |
47+ | 8-11 | 0x08 | seq | uint32_t | 页轮转序号(递增) |
48+ | 12 | 0x0C | current_layer | uint8_t | 当前层(高频保存) |
49+ | 13-251 | 0x0D ~ 0xFB | reserved | uint8_t[ 239] | 预留 |
50+ | 252-255 | 0xFC ~ 0xFF | crc32 | uint32_t | 整页校验(末尾字段除外) |
51+
52+ 加载时扫描 4 页,校验 ` magic/version/crc32 ` 后选择 ` seq ` 最大的有效页。
53+
54+ #### runtime 页(规划 v2,建议)
55+
56+ 为后续模式恢复与蓝牙槽位扩展预留字段,建议在 ` version=0x0002 ` 时使用以下布局(当前未启用):
57+
58+ | 字节 | 偏移 | 字段 | 类型 | 说明 |
59+ | :--- | :--- | :--- | :--- | :--- |
60+ | 0-3 | 0x00 | magic | uint32_t | ` \"RUNT\" ` |
61+ | 4-5 | 0x04 | version | uint16_t | ` 0x0002 ` (规划) |
62+ | 6-7 | 0x06 | flags | uint16_t | runtime 标志位 |
63+ | 8-11 | 0x08 | seq | uint32_t | 页轮转序号 |
64+ | 12 | 0x0C | current_layer | uint8_t | 当前层 |
65+ | 13 | 0x0D | active_mode | uint8_t | 当前模式(USB/BLE/2.4G,可选持久化) |
66+ | 14 | 0x0E | profile_slot_reserved | uint8_t | 预留(未来 BLE 多槽位) |
67+ | 15 | 0x0F | runtime_flags | uint8_t | 预留运行态标志 |
68+ | 16-251 | 0x10 ~ 0xFB | reserved | uint8_t[ 236] | 预留 |
69+ | 252-255 | 0xFC ~ 0xFF | crc32 | uint32_t | 整页校验 |
2970
3071### 块内偏移布局
3172
@@ -44,12 +85,12 @@ MeowKeyboard CH592F 固件在 DataFlash 中的存储布局说明。
4485
4586---
4687
47- ## 配置头 kbd_config_header_t (32 字节, 偏移 0x000)
88+ ## 配置头 kbd_config_header_t (32 字节, 偏移 0x000 / 槽位内 )
4889
4990| 字节 | 偏移 | 字段 | 类型 | 说明 |
5091| :--- | :--- | :--- | :--- | :--- |
5192| 0-3 | 0x00 | magic | uint32_t | 魔数 ` 0x4D454F57 ` ("MEOW") |
52- | 4-5 | 0x04 | version | uint16_t | 配置版本 ` 0x0101 ` |
93+ | 4-5 | 0x04 | version | uint16_t | 配置版本 ` 0x0102 ` |
5394| 6-7 | 0x06 | flags | uint16_t | 标志位 |
5495| 8-11 | 0x08 | crc32 | uint32_t | 各配置块 CRC32 异或校验 |
5596| 12-15 | 0x0C | save_count | uint32_t | 保存计数 |
@@ -64,7 +105,8 @@ MeowKeyboard CH592F 固件在 DataFlash 中的存储布局说明。
64105| 0 | 0x100 | default_mode | uint8_t | 默认模式 (0=USB, 1=BLE, 2=2.4G预留) |
65106| 1 | 0x101 | auto_sleep_min | uint8_t | 自动休眠时间(分钟,0=禁用) |
66107| 2 | 0x102 | debounce_ms | uint8_t | 按键消抖时间(毫秒) |
67- | 3-63 | 0x103 | reserved | uint8_t[ 61] | 保留 |
108+ | 3 | 0x103 | log_enabled | uint8_t | HID 日志开关 (v1.2+) |
109+ | 4-63 | 0x104 | reserved | uint8_t[ 60] | 保留 |
68110
69111---
70112
@@ -73,7 +115,7 @@ MeowKeyboard CH592F 固件在 DataFlash 中的存储布局说明。
73115| 字节 | 偏移 | 字段 | 类型 | 说明 |
74116| :--- | :--- | :--- | :--- | :--- |
75117| 0 | 0x200 | num_layers | uint8_t | 层数 (1-5) |
76- | 1 | 0x201 | current_layer | uint8_t | 当前激活层 |
118+ | 1 | 0x201 | current_layer | uint8_t | 当前激活层(基础值,启动后可被 runtime 热数据覆盖) |
77119| 2 | 0x202 | default_layer | uint8_t | 默认层 |
78120| 3 | 0x203 | reserved | uint8_t | 保留 |
79121| 4-163 | 0x204 | layers[ 5] | kbd_layer_t[ 5] | 5 层 × 32 字节 |
@@ -173,24 +215,34 @@ MeowKeyboard CH592F 固件在 DataFlash 中的存储布局说明。
173215
1742161 . 通过 HID 命令修改 RAM 中的配置(如 RGB_SET)
1752172 . 发送 ** CFG_SAVE** (0x10) 触发保存
176- 3 . 固件擦除 0x0000 起 4KB 块,写入整块数据
218+ 3 . 固件将配置写入下一个 ** 1KB 配置槽** (按 ` 256B ` 页差异擦写)
219+ 4 . 同步写入 runtime 热数据页(保存当前层)
220+
221+ ### 高频层切换(不走 CFG_SAVE)
222+
223+ - ` current_layer ` 变化时,仅写 ` 0x0C00~0x0FFF ` 的 runtime 热数据页(` 256B ` )
224+ - 不重写整份配置
177225
178226---
179227
180228## 注意事项
181229
182230### 配置区整体
183231
184- ::: warning 整块擦写
185- 配置区 0x0000 ~ 0x0FFF 作为一个 ** 4KB 块 ** 整体擦除和写入,无法单独更新某一配置块 。每次 CFG_SAVE 都会重写全部配置(含头部、系统、键映射、FN、RGB) 。
232+ ::: tip 小配置小擦写
233+ 配置区使用 ** 3×1KB 槽位轮转 + 256B 页差异写 ** 。每次 CFG_SAVE 不再整块擦写 4KB,只更新发生变化的配置页 。
186234:::
187235
188236::: tip 魔数与版本校验
189- 加载时仅校验 ` magic == 0x4D454F57 ` 和主版本号 ` (version >> 8) ` 。魔数错误或主版本不匹配时,将回退到默认配置, ** 不会 ** 从 Flash 读取任何配置数据 。
237+ 加载时扫描配置槽,校验 ` magic ` 、主版本号与 ` crc32 ` ,选择 ` save_count ` 最大的有效槽位。无有效槽位时回退默认配置 。
190238:::
191239
192240::: info CRC 校验
193- ` crc32 ` 由系统、键映射、FN、RGB 四块的 CRC32 异或得出,写入时计算。当前固件** 加载时不校验 CRC** ,仅作存储用。
241+ ` crc32 ` 由系统、键映射、FN、RGB 四块的 CRC32 异或得出,写入时计算,** 加载时会校验** 。
242+ :::
243+
244+ ::: info 热数据页环
245+ ` current_layer ` 单独存放在 runtime 热数据页环(4×256B),高频切层只写热数据页,减少配置区磨损。
194246:::
195247
196248### 按键映射
@@ -258,3 +310,53 @@ CFG_RESET 会调用 `KBD_Config_Reset`:加载默认配置、**清除全部 8
258310:::
259311
260312### 升级与迁移
313+
314+ - 新布局将 ` 0x0C00~0x0FFF ` 作为 runtime 热数据区,不再作为第 4 个配置槽使用。
315+ - 启动时会优先扫描新配置槽;若无有效配置,会尝试读取旧版 ` 0x0C00 ` 配置并自动迁移。
316+ - 迁移成功后,后续保存将只使用新布局(3 槽配置区 + 1KB runtime 热数据区)。
317+
318+ ---
319+
320+ ## 推荐优化方案(规划)
321+
322+ > 以下为下一版可选方案,当前固件尚未完全实现。
323+
324+ ### 核心思路
325+
326+ - 小配置使用 ` 256B ` 页环(分区日志页)
327+ - 宏数据保持 ` 4KB ` 块擦写
328+ - 每个分区独立 ` seq + crc + commit ` ,按分区恢复
329+
330+ ### 推荐布局(示例)
331+
332+ | 地址范围 | 大小 | 用途 |
333+ | :------- | :--- | :--- |
334+ | 0x0000 ~ 0x03FF | 1KB | ` base ` 页环(系统/FN/RGB) |
335+ | 0x0400 ~ 0x07FF | 1KB | ` keymap ` 页环 |
336+ | 0x0800 ~ 0x0BFF | 1KB | ` meta ` 页环(迁移/统计/版本) |
337+ | 0x0C00 ~ 0x0FFF | 1KB | ` runtime ` 热数据页环(层号/模式) |
338+ | 0x1000 ~ 0x4FFF | 16KB | 宏区(4KB 块擦写) |
339+
340+ ### 页记录头(建议)
341+
342+ - ` magic `
343+ - ` version `
344+ - ` type ` (` BASE/KEYMAP/RUNTIME/META ` )
345+ - ` state ` (空/写入中/有效)
346+ - ` seq `
347+ - ` payload_len `
348+ - ` crc32 `
349+
350+ ### 写入流程(建议)
351+
352+ 1 . 擦除目标 ` 256B ` 页
353+ 2 . 写入 ` header(state=写入中) ` 和 payload
354+ 3 . 校验 ` crc32 `
355+ 4 . 将 ` state ` 写为有效(只做 ` 1 -> 0 ` 位变化)
356+
357+ ### 优点
358+
359+ - ` current_layer ` 高频更新只写 ` runtime ` 页
360+ - 改 RGB 不会写 ` keymap `
361+ - 改键位不影响 ` base/runtime `
362+ - 单分区损坏不影响其他分区恢复
0 commit comments