Skip to content

Commit fd5091c

Browse files
committed
feat: 重构存储架构、完善 BLE/USB HID 及 Studio PWA 支持
- 固件存储重构为冷热分离架构 (配置槽位轮转 + 运行时热数据页环) - 完善 BLE HID 多模式支持与 USB HID 描述符 - Studio 接入 PWA (vite-plugin-pwa),新增 toast 通知服务 - 更新无线文档 (BLE/DataFlash/HID/TMOS),补充开发指南 - 优化 CMake 构建系统与工具链配置 - 迁移 flash.py/setup.py 至 tools/scripts/,清理旧工程文件
1 parent e153974 commit fd5091c

52 files changed

Lines changed: 6034 additions & 1133 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/code-quality.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575

7676
- name: Install dependencies
7777
working-directory: tools/studio
78-
run: pnpm install
78+
run: pnpm install --frozen-lockfile
7979

8080
- name: Run ESLint
8181
working-directory: tools/studio

.github/workflows/deploy-docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242

4343
- name: Install dependencies
4444
working-directory: docs
45-
run: pnpm install
45+
run: pnpm install --frozen-lockfile
4646

4747
- name: Build
4848
working-directory: docs

.github/workflows/firmware-build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ jobs:
4343
path: |
4444
firmware/CH592F/build/release/CH592F.bin
4545
firmware/CH592F/build/release/CH592F.hex
46+
firmware/CH592F/build/release/CH592F.map
4647
retention-days: 7

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838

3939
# 快速开始
4040

41+
- 文档首页:[`docs/index.md`](./docs/index.md)
42+
- 有线款固件:[`firmware/CH552G/README.md`](./firmware/CH552G/README.md)
43+
- 无线款固件:[`firmware/CH592F/README.md`](./firmware/CH592F/README.md)
44+
- 改键工具(Web / PWA):[`tools/studio/README.md`](./tools/studio/README.md)
45+
4146
# 环境
4247

4348
## 有线款
@@ -48,6 +53,10 @@
4853

4954
[无线款](./firmware/CH592F/README.md)
5055

56+
## 改键工具
57+
58+
[BinaryKeyboard Studio](./tools/studio/README.md)
59+
5160
# 贡献
5261

5362
[![Contributors](https://contrib.rocks/image?repo=MeowKJ/BinaryKeyboard)](https://github.com/MeowKJ/BinaryKeyboard/graphs/contributors)
@@ -69,4 +78,4 @@
6978
- **文档与素材(Docs & Assets)**:遵循 [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh-Hans)
7079
适用范围:`/Hardware/**``/Models/**`
7180

72-
---
81+
---

docs/.vitepress/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export default defineConfig({
5858
{ text: '固件开发', link: '/wireless/dev' },
5959
{ text: 'HID 通讯协议', link: '/wireless/hid' },
6060
{ text: '低功耗蓝牙', link: '/wireless/ble' },
61+
{ text: 'TMOS 调度', link: '/wireless/tmos' },
6162
{ text: 'DataFlash 布局', link: '/wireless/dataflash' },
6263
{ text: 'RGB 灯效架构', link: '/wireless/rgb-architecture' },
6364
]

docs/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
"type": "module",
66
"packageManager": "pnpm@9.15.0",
77
"scripts": {
8-
"dev": "vitepress dev",
8+
"dev": "vitepress dev --host 0.0.0.0 --port 5174 --no-open",
99
"build": "vitepress build",
10-
"preview": "vitepress preview"
10+
"preview": "vitepress preview --host 0.0.0.0 --port 5174"
1111
},
1212
"devDependencies": {
1313
"vitepress": "^1.5.0"

docs/wireless/ble.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,5 @@ MeowKeyboard 无线版基于 CH592F 的 BLE5.4 协议栈,实现 HID over GATT
160160

161161
- [HID 通讯协议](./hid.md) - 报告格式与配置命令
162162
- [DataFlash 布局](./dataflash.md) - SNV 区与 BLE 存储
163+
- [TMOS 调度](./tmos.md) - 任务/事件/消息与定时处理
163164
- [固件开发](./dev.md) - 编译与调试

docs/wireless/dataflash.md

Lines changed: 115 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

174216
1. 通过 HID 命令修改 RAM 中的配置(如 RGB_SET)
175217
2. 发送 **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

Comments
 (0)