diff --git a/.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PARTITION_REPORT.md b/.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PARTITION_REPORT.md new file mode 100644 index 0000000..86dac19 --- /dev/null +++ b/.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PARTITION_REPORT.md @@ -0,0 +1,115 @@ +# PARTITION_REPORT — Phase 2 分区表调整验证报告 + +> 阶段: `phase_02_partition_resize` +> 日期: 2026-05-13 +> 状态: ✅ **完成** + +## 1. 调整前后对比 + +| 分区 | 旧(Phase 1) | 新(Phase 2) | 变化 | +|------|--------------|--------------|------| +| nvs | 0x9000 / 16KB | 0x9000 / 16KB | 不变 | +| otadata | 0xD000 / 8KB | 0xD000 / 8KB | 不变 | +| phy_init | 0xF000 / 4KB | 0xF000 / 4KB | 不变 | +| **model** | **0x10000 / 64KB** | **— 已移除** | -64KB | +| **ota_0** | 0x20000 / 6.5MB | **0x10000 / 5.5MB** | **-1MB**,起始偏移前移 | +| **ota_1** | 0x6A0000 / 6.5MB | **0x590000 / 5.5MB** | **-1MB**,起始偏移前移 | +| **storage** | 0xD20000 / 2.875MB | **0xB10000 / 4.9375MB** | **+2.0625MB** | +| 合计 | 16MB | 16MB | — | + +## 2. 编译验证(=n 数字人 RTC 模式) + +| 项 | 结果 | +|----|------| +| `idf.py build` | ✅ 通过 | +| `kapi.bin` 大小 | **4,857,344 bytes (4.63 MB)** ≤ 5.5MB | +| ota_0 余量 | **0.87 MB (15.8%)** 成长 buffer | +| `storage.bin` 大小 | 5,177,344 bytes (4.94 MB) ≈ SPIFFS 容量 | +| 分区表生成 | ✅ ota_0 5632K + ota_1 5632K + storage 5056K | + +## 3. 编译验证(=y 双模式,G7 兼容性) + +| 项 | 结果 | +|----|------| +| `idf.py build` 链接 | ✅ 通过,`kapi.bin` 生成 | +| `kapi.bin` 大小 | **6,345,184 bytes (6.05 MB)** > 5.5MB | +| Partition check | ❌ **失败**:超出 ota_0 容量 0x8D1E0 (577KB) | +| 代码层 G7 状态 | ✅ **达成**:全部源码可编译,链接产物可生成 | +| 烧录 G7 状态 | ⚠️ **降级**:当前分区表下双模式固件不可烧录 | + +### 3.1 =y 烧录限制说明 + +数字人 RTC 单一形态项目**只用 =n 固件**,=y 双模式从 Phase 2 起进入"代码归档"状态: +- 源码完整保留,可恢复编译 +- 链接产物 `kapi.bin` 可生成(证明无符号缺失) +- 但因 16MB Flash 物理限制 + 双模式代码量(6.05MB),装不进 5.5MB 分区 +- Phase 3 物理移除吧唧专属 .rodata 资源(emoji 图片、SquareLine UI 图片等)后,=y 大小可能降到 5.5MB 以下 + +## 4. 烧录运行时验证(=n 模式) + +| 验收项 | 结果 | +|--------|------| +| 烧录无错误 | ✅ `Wrote 5177344 bytes` 验证成功 | +| 启动运行 ota_0 分区 | ✅ `Running partition: ota_0` | +| SPIFFS 自动挂载 | ✅ `BG_GIF: SPIFFS 未挂载,自动挂载...` 成功 | +| 数字人 GIF 加载 | ✅ `GIF 已加载到 PSRAM: /spiflash/hiyori_m05.gif (2327.4 KB)` | +| 背景图加载 | ✅ `背景图已解码: 360x360 (253.1 KB RGB565)` | +| NVS 数据完整 | ✅ `VolcRtcProtocol: NVS凭证已加载:secret=1 appid=1 device_name=d0_cf_13_03_bb_f0` | +| AI 对话模式启动 | ✅ `🤖 AI对话模式启动` | +| AudioCodec 启动 | ✅ `AudioCodec: Audio codec started`(冷启动一次失败属 Phase 0 历史问题) | +| WiFi 连接 | ✅ `WifiBoard: Starting WiFi connection` | +| RTC WebSocket 协议 | ✅ `Application: ✅ WebSocket协议初始化完成` | +| 堆内存余量 | ✅ `free_heap=5225356`(5.2MB) | + +## 5. 关键技术验证 + +### 5.1 NVS 数据保留 + +NVS 分区位置(0x9000)和大小(0x4000)未变,**WiFi 凭据、设备配置全部保留**。无需重新配网。 + +### 5.2 SPIFFS 数据保留 + +SPIFFS 分区位置从 `0xD20000 / 2.875MB` 改为 `0xB10000 / 4.9375MB`——**位置改变,但因为 `idf.py flash` 同时烧录新 storage.bin,数据完整迁移**。 + +存放的资源(PoC 阶段): +- `Background_360x360.jpg` (20KB) +- `hiyori_m05.gif` (2.3MB) +- 其他历史图片资源 + +### 5.3 OTA 双分区可用性 + +启动日志确认 `Running partition: ota_0`,证明 OTA 双分区机制仍然工作正常。后续生产环境可通过 OTA 推送固件升级到 ota_1,再切换。 + +## 6. Phase 3 SPIFFS 容量预算 + +Phase 3 计划装入 3 个 hiyori GIF: + +| GIF | 原始大小 | 压缩后预期 | +|-----|---------|----------| +| m06(默认/积极) | 1.3MB | 不压缩 | +| m07(思考/疲倦) | 1.1MB | 不压缩 | +| m03(负面/严肃) | 3.3MB | gifsicle `--lossy=30 --colors 128` 压到 ~1.5MB | +| **合计预期** | **5.7MB** | **~3.9MB** | + +加上 `Background_360x360.jpg`(20KB),Phase 3 总占用约 **3.9MB**,在 SPIFFS 4.9375MB 容量内 ✅,留约 1MB 余量。 + +## 7. 风险事项 + +| 风险 | 实际发生 | 处置 | +|------|---------|------| +| =y 双模式装不进新分区 | ✅ 已发生 | 记录入报告,不阻塞数字人 RTC 单一形态项目 | +| 冷启动 codec I2C 失败 | ✅ 出现一次(Phase 0 历史问题) | 已知 ESP32-S3 + ES8311 冷启动时序问题,软重启后正常 | +| NVS 数据丢失 | 未发生 | NVS 分区不变,数据保留 | +| storage.bin 装不进 SPIFFS | 未发生 | storage.bin 5.17MB(与 SPIFFS 4.94MB 一致,spiffsgen 自动调整) | + +## 8. Phase 2 结论 + +**全部验收项通过**: +- ✅ 新分区表生效 +- ✅ =n 固件 4.63MB 装入 5.5MB ota_0,有 0.87MB 成长 buffer +- ✅ SPIFFS 扩容到 4.94MB,为 Phase 3 数字人 GIF 资源预留充足空间 +- ✅ NVS / SPIFFS / OTA 全部数据完整保留 +- ✅ AI 对话模式启动、Codec 工作、WiFi 连接、RTC 协议都正常 +- ⚠️ =y 双模式装不下(**预期行为**,Phase 3 资源精简后可能恢复) + +下一步:Phase 3 — GIF 资源准备(gifsicle 处理 m03/m06/m07)。 diff --git a/.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PLAN.md b/.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PLAN.md new file mode 100644 index 0000000..b0aeab6 --- /dev/null +++ b/.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PLAN.md @@ -0,0 +1,232 @@ +# Phase 2 PLAN — 分区表调整 + +> 里程碑: `digital_human_rtc` +> 阶段目标: 调整 `partitions.csv`,扩容 SPIFFS 装下 3 个 hiyori GIF(约 5.7MB);同时保留双 OTA 升级能力;为固件预留 1MB 成长空间。 + +## 0. 当前分区表实际状态(已核实) + +``` +nvs data nvs 0x9000 0x4000 # 16KB +otadata data ota 0xd000 0x2000 # 8KB +phy_init data phy 0xf000 0x1000 # 4KB +model data spiffs 0x10000 0x10000 # 64KB(暂未使用,可移除) +ota_0 app ota_0 0x20000 0x680000 # 6.5MB +ota_1 app ota_1 0x6a0000 0x680000 # 6.5MB +storage data spiffs 0xD20000 0x2E0000 # 2.875MB ← Phase 3 需要扩容 +``` + +合计:16MB ✅ +当前 `kapi.bin` =n 版本:**4.63MB**(占 ota_0 容量的 71%) + +## 1. 决策方案(已与用户对齐) + +**用户选择**: 5.5MB 双 OTA + 4.9MB SPIFFS,**移除 model 分区**。 + +### 1.1 新分区表 + +```csv +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x4000, +otadata, data, ota, 0xd000, 0x2000, +phy_init, data, phy, 0xf000, 0x1000, +ota_0, app, ota_0, 0x10000, 0x580000, +ota_1, app, ota_1, 0x590000, 0x580000, +storage, data, spiffs, 0xB10000, 0x4F0000, +``` + +### 1.2 空间分配 + +| 分区 | 起始偏移 | 大小 | 大小(十进制) | +|------|---------|------|--------------| +| nvs | 0x9000 | 0x4000 | 16 KB | +| otadata | 0xD000 | 0x2000 | 8 KB | +| phy_init | 0xF000 | 0x1000 | 4 KB | +| **ota_0** | **0x10000** | **0x580000** | **5.5 MB** | +| **ota_1** | **0x590000** | **0x580000** | **5.5 MB** | +| **storage**(SPIFFS) | **0xB10000** | **0x4F0000** | **4.9375 MB** | + +合计校验:`0xB10000 + 0x4F0000 = 0x1000000 = 16 MB` ✅ + +### 1.3 vs 旧分区表对比 + +| 分区 | 旧 | 新 | 变化 | +|------|-----|-----|------| +| model | 0x10000 (64KB) | **移除** | 释放 64KB | +| ota_0 | 0x680000 (6.5MB) | 0x580000 (5.5MB) | **缩 1MB** | +| ota_1 | 0x680000 (6.5MB) | 0x580000 (5.5MB) | **缩 1MB** | +| storage | 0x2E0000 (2.875MB) | 0x4F0000 (4.9375MB) | **扩 2.0625MB** | + +净释放:1+1+0.0625-2.0625 = **0MB**(完美匹配 16MB Flash) +SPIFFS 净扩容:**+2.0625MB** + +### 1.4 容量决策依据 + +- 当前 =n 固件 4.63MB → 5.5MB ota 留 **0.87MB(19%)** 成长 buffer,可支持 Phase 3-6 新增代码 +- 当前 =y 固件 6.05MB → ⚠️ **超过 5.5MB**!双模式版本将装不下,但本里程碑只产出 =n 版本,G7 验收仅靠编译验证(=y 编译通过即可,不必烧录) +- SPIFFS 4.9375MB: + - Phase 3 用 3 个 GIF(m03=3.3MB + m06=1.3MB + m07=1.1MB = 5.7MB)→ **超出!需要 gifsicle 优化压缩** + - 备用方案:精选 m06+m07+ 一个新压缩的 m03 → 总目标 < 4.9MB + - Phase 3 优化策略:`gifsicle --lossy=30 --colors 128` 把 m03 压到 < 2MB + +## 2. 任务清单 + +### Task 2.1: 修改 partitions.csv + +**文件**: `/Users/rdzleo/Desktop/Baji_Rtc_Toy/partitions.csv` + +**完整新内容**: +```csv +# ESP-IDF Partition Table +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x4000, +otadata, data, ota, 0xd000, 0x2000, +phy_init, data, phy, 0xf000, 0x1000, +ota_0, app, ota_0, 0x10000, 0x580000, +ota_1, app, ota_1, 0x590000, 0x580000, +storage, data, spiffs, 0xB10000, 0x4F0000, +``` + +**验证**: +- `idf.py partition-table` 输出分区表正确 +- 总和不超 16MB Flash + +**commit 消息**: `chore(partitions): 16MB Flash 分区调整 - 双 OTA 5.5MB + SPIFFS 4.9MB(移除 model 分区)` + +--- + +### Task 2.2: 编译验证(=n 模式) + +**步骤**: +```bash +cd /Users/rdzleo/Desktop/Baji_Rtc_Toy +source /Users/rdzleo/esp/esp-idf/export.sh > /dev/null 2>&1 +# 确保 sdkconfig=n +grep "BAJI_BADGE_MODE" sdkconfig +# 重新编译(partition 改动需要 reconfigure) +idf.py fullclean +idf.py build 2>&1 | tail -10 +idf.py partition-table +idf.py size > .planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/size_after.txt +ls -la build/*.bin >> .planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/size_after.txt +``` + +**验证标准**: +- ✅ `idf.py build` 编译通过 +- ✅ `kapi.bin` ≤ 5.5MB(ota_0 容量) +- ✅ `storage.bin` ≤ 4.9MB(SPIFFS 容量)—— 当前 storage.bin 3MB,扩到 5MB 后还有余量 +- ✅ `idf.py partition-table` 显示新分区表 + +**预期产出**: +- `kapi.bin` ≈ 4.63MB(不变,与代码无关) +- `storage.bin` 可扩展(当前 3MB,Phase 3 装 GIF 后会增大) + +**不产出 commit**(仅验证步骤) + +--- + +### Task 2.3: 编译验证(=y 模式,G7 双向编译) + +**步骤**: +```bash +sed -i.bak 's/# CONFIG_BAJI_BADGE_MODE is not set/CONFIG_BAJI_BADGE_MODE=y/' sdkconfig +idf.py fullclean +idf.py build 2>&1 | tail -10 +ls -la build/*.bin +# 切回 =n +sed -i.bak 's/CONFIG_BAJI_BADGE_MODE=y/# CONFIG_BAJI_BADGE_MODE is not set/' sdkconfig +rm -f sdkconfig.bak +idf.py reconfigure +``` + +**验证标准**: +- ✅ `=y` 模式编译通过(双模式 G7 兼容性) +- ⚠️ **可能 `kapi.bin` > 5.5MB**(双模式固件 6.05MB > 5.5MB 容量) +- 如果 =y kapi.bin > 5.5MB:**记录但不阻塞 Phase 2**,因为: + - 数字人 RTC 单一形态项目只用 =n 固件 + - =y 仅用于"代码可恢复性"验证,不需要烧录 + - Phase 3 物理移除吧唧专属资源后,=y 大小可能降到 5.5MB 以下 + +**不产出 commit**(仅验证步骤) + +--- + +### Task 2.4: 烧录 + 运行时验证 + +**步骤**: +```bash +idf.py -p /dev/cu.usbmodem834401 flash 2>&1 | tail -5 +``` + +**python 串口监控(30 秒)验证**: + +```python +# 关键验证项 +1. SPIFFS 挂载成功(partition_label="storage") +2. 数字人 GIF 加载成功(/spiflash/hiyori_m05.gif 仍在) +3. 背景图加载成功(/spiflash/Background_360x360.jpg 仍在) +4. AI 对话模式启动正常(与 Phase 1 验收一致) +5. WiFi 自动连接 +6. RTC WebSocket 协议初始化 +``` + +**关键风险**: 分区调整可能导致 NVS 数据丢失(WiFi 凭据、设备配置)—— 但 NVS 分区位置(0x9000)和大小(0x4000)**未变**,应该不丢数据。 + +**验证标准**: +- ✅ SPIFFS 自动挂载(`esp_spiffs_info` 返回 total ≈ 4.9MB) +- ✅ 数字人 GIF 显示正常 +- ✅ 30 秒无崩溃重启 + +**不产出 commit**(仅验证步骤) + +--- + +### Task 2.5: 生成 PARTITION_REPORT.md + +**文件**: `.planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PARTITION_REPORT.md` + +**内容**: +- 旧/新分区表对比 +- 实际 SPIFFS 容量(`esp_spiffs_info` 输出) +- =n 固件大小(kapi.bin) +- =y 固件大小(双模式编译验证结果) +- Phase 3 SPIFFS 容量预算(3 个 hiyori GIF 装下 vs 需要 gifsicle 进一步压缩) + +**commit 消息**: `docs(phase02): 分区表调整验证报告(PARTITION_REPORT.md)` + +## 3. 任务顺序 + +``` +Task 2.1 (修改 csv) → Task 2.2 (=n 编译) → Task 2.3 (=y 编译,G7) → Task 2.4 (烧录) → Task 2.5 (报告) +``` + +串行执行,每步独立验证。 + +## 4. 风险与回滚 + +| 风险 | 概率 | 影响 | 缓解 | +|------|------|------|------| +| NVS 数据丢失(WiFi 凭据) | 低 | 重新配网 | NVS 分区位置/大小不变,理论上不丢;若丢,重新走 BLE 配网即可 | +| 旧 OTA 数据残留导致启动失败 | 低 | 启动失败 | 首次烧录用 `idf.py erase-flash` + `idf.py flash`,确保 Flash 全部重写 | +| `=y` 固件 > 5.5MB 无法烧录 | 高(实际就是这样) | =y 烧录不可用 | 不阻塞 Phase 2,记录入风险清单,Phase 3 解决 | +| storage.bin > 4.9MB 烧录失败 | 中(当前 3MB,Phase 3 GIF 装入后可能超) | SPIFFS 镜像装不下 | Phase 3 用 gifsicle 控制 GIF 总体积 ≤ 4.5MB | + +**回滚策略**: 如果分区调整后烧录失败/数据异常,`git revert` Task 2.1 commit 即可恢复旧分区表,重新烧录即可。 + +## 5. Phase 2 完成验收清单 + +- [ ] Task 2.1 commit 完成 +- [ ] Task 2.2 `=n` 编译通过 + kapi.bin ≤ 5.5MB +- [ ] Task 2.3 `=y` 编译通过(即使 kapi.bin > 5.5MB 也接受,记录入报告) +- [ ] Task 2.4 烧录后开机正常,SPIFFS 挂载显示 4.9MB +- [ ] Task 2.5 PARTITION_REPORT.md 已生成 commit +- [ ] WiFi 凭据/NVS 数据未丢失 +- [ ] AI 对话模式启动正常 +- [ ] 整个 Phase 2 全部 commit + .planning/ 文档合并为 1 个大 commit 推送 gitea + GitHub(参考 Phase 1 合并策略) + +## 6. Phase 2 不做的事 + +- ❌ 不修改任何 C/C++ 源代码 +- ❌ 不动 Phase 1 的 Kconfig 开关 +- ❌ 不准备 GIF 资源(Phase 3 才做) +- ❌ 不动 `main/Kconfig.projbuild` diff --git a/partitions.csv b/partitions.csv index ccef2b6..be43545 100644 --- a/partitions.csv +++ b/partitions.csv @@ -1,9 +1,8 @@ # ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags +# Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x4000, otadata, data, ota, 0xd000, 0x2000, phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0x10000, -ota_0, app, ota_0, 0x20000, 0x680000, -ota_1, app, ota_1, 0x6a0000, 0x680000, -storage, data, spiffs, 0xD20000, 0x2E0000, +ota_0, app, ota_0, 0x10000, 0x580000, +ota_1, app, ota_1, 0x590000, 0x580000, +storage, data, spiffs, 0xB10000, 0x4F0000,