文件
phonerail/firmware/HANDOFF.md
T
zhou yang和Claude Opus 5.5 ae1aad3b7c 固件 C2:OTA 双槽 + 失败回滚(已上板实测正常 / 哈希错 / 回滚三条路径)
- 分区重排(16 MB,nvs 0x9000 不动):ota_0 / ota_1 各 3 MB、otadata 0x610000、evlog 挪到 0x612000;
  flash 大小改正为 16 MB;开 CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
- ota.{h,c}(宿主机可测):URL / sha256 校验、判定(下载中 busy、待验证拒、同镜像不重下)、健康判据
- ota_esp.{h,c}:t_ota 任务经 HTTP 下载、边下边算 sha256、核 project_name 后切启动分区;
  新固件 120 s 内连不上 broker 就回滚(t_link 判 + esp_timer 兜底);重启前等回应发出、事件落盘
- 新命令 ota = 13(两条链路都收,reboot 默认 false:复位 = 五台手机断电一次);status 加 ota 一块;
  新事件 LOG_EV_OTA = 18;PROJECT_VER 取 PHONERAIL_FW_VERSION
- test_ota.c 13 例,全工程 442 例全绿;版本 0.1.0-c2
- 服务器:nginx 7765 只放行 /fw/<16 hex>.bin(不过门户,路由器转发已加);tools/ota_push.py 推送;
  rack protocol.py 加事件 18 / 命令 13(已部署)
- 板 B:推送到自证健康 19 s;错哈希不切分区;删掉 broker 账号后 120 s 回滚,bad 报出被回滚的版本

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-27 14:03:13 +08:00

6.4 KiB
原始文件 Blame 文件历史

交接

更新:2026-09-27 完成 C2 OTA(双槽 + 失败回滚,已上板实测正常 / 哈希错 / 回滚三条路径)

一句话现状

ota 命令(经 MQTT 或 USB)给 URL + sha256 + size,板子自己经 HTTP 下载、边下边算哈希、对上才切启动分区; 新固件 120 s 内连不上 broker 就回滚。26 个 ctest、442 个用例全绿,idf.py build 通过(0xF32E0,槽 3 MB,余 68%)。 板 B(COM5)现在跑 0.1.0-c2(最后一次就是经 OTA 推上去的)。定稿写在需求 §10.8「C2 定稿的 OTA」。

怎么推固件

python tools/ota_push.py b81f3fc9c8bc            # 推 build/phonerail.bin:只下载 + 校验 + 切分区,下次复位生效
python tools/ota_push.py b81f3fc9c8bc --reboot   # 校验过就立刻重启 —— ⚠️ 五台手机硬断电一次
python tools/ota_push.py b81f3fc9c8bc --status

它把镜像传到服务器 /root/phonerail/fw/<sha 前 16 位>.bin(nginx 7765,只放行这种文件名,不过门户), 再在服务器上用后端账号经 1884 发命令、盯遥测。rack 管理界面还没有 OTA 按钮(下一步可以做)。

下一步(没人定,候选)

  • rack 界面加「推固件」:上传 .bin → 后端算哈希、放进 fw 目录、发 ota;界面上 reboot 要二次确认(五路全断)。
  • 「重启不断电」:ESP 复位时 EN 被下拉 ⇒ OTA / 回滚都会让五台手机掉电一次。要避免得在复位前 gpio_hold_en 各路 EN、 并改 bringup 第 1 步「安全态」只在上电复位时做 —— 动的是安全链,要先讨论。
  • 服务器 fw 目录不会自动清理旧镜像(每个 ~1 MB,问题不大)。

C2 改了什么

  • partitions.csv 重排(16 MB):nvs 0x9000 没动;ota_0 / ota_1 各 3 MB;otadata 0x610000;evlog 挪到 0x612000(历史事件清空了一次)。
  • sdkconfig.defaults + sdkconfig:flash 16 MB(之前误写 8 MB);CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y(bootloader 配置,只有 USB 整片烧才生效)。
  • main/ota.{h,c} 新(宿主机可测):URL / 哈希校验、判定(busy / 待验证拒 / 同镜像不重下)、健康判据。
  • main/ota_esp.{h,c} 新:t_ota 任务(esp_http_client + mbedtls sha256 + OTA_WITH_SEQUENTIAL_WRITES,每块让一个 tick)、 核 project_name、切分区;t_link 里判健康 / 到点重启(先等 2 s 让回应发出去、事件落盘);esp_timer 150 s 兜底回滚。
  • cmd 新命令 ota=13(cmd_net.c 的 do_ota);status 多 ota 一块;evlog 新事件 LOG_EV_OTA=18。
  • 顶层 CMakeLists.txt:PROJECT_VER 取 PHONERAIL_FW_VERSION(否则镜像头版本是 git describe,回滚后 ota.bad 报 79c9f8b-dirty)。
  • test/test_ota.c 新(13 例);test_cmd / test_evlog 的冻结数字表各加一行。
  • tools/ota_push.py 新;rack/deploy/nginx-phonerail-fw.conf 新(已部署);rack/backend/prrack/protocol.py 加事件 18 / 命令 13(已部署)。

上板实测(板 B,五槽空)

正常:c2 → c2-t1 经 MQTT --reboot:下载 ≈8 s,推送到自证健康 19 s;事件 18/1 → 18/2 → 18/6 → BOOT → 18/4
哈希错:err "hash"、got 996064、固件不变;下载 20 s 里 t_safety skipped 0
回滚:服务器删掉板子 broker 账号 → USB 发同镜像 reboot:true → 起在 c2-rb(pend true)→ 120 075 ms 记 18/5 → 回到 c2-t1、bad 报版本
      (账号已原样恢复,备份已删)
收尾:c2-t1 → 正式 0.1.0-c2 经 MQTT --reboot 成功

踩到的坑(只写会再犯的)

  • 路由器不是整机 DMZ:新开的 7765 公网 TCP 都连不上,用户手动加了转发才通(本机测公网要 curl --noproxy '*', 否则 7890 代理回的 502 会被当成服务器的)。
  • 本机 PowerShell Set-Content -Encoding ascii 改 phonerail.h 把中文注释写成 ??(已 git checkout 还原)—— 改它一律用 sed。
  • Git Bash heredoc 里的 Python 写 '\0' 会变成真 NUL 字节进源码;含反斜杠的替换写成 .py 文件再跑。
  • 宿主机 bash host/test.sh 用 -j 4 在 cygwin 上偶发「link: Subprocess aborted」,cmake --build build -j 1 就过。

其它挂着的事

  • 风扇还没下单购买(2026-09-27):板 B 两路报 rpm 0 + 停转是预期的。到货插上后看 status.fan.rpm;在转却仍是 0 再查 Q9/Q10 与 PCNT。
  • 风扇闭环四个阈值 + 占空比下限 + PPR 都是「待上板实测」(t_thermal.h),手机上架跑满载之后再定。
  • A15 留下的:I²C 总线挂死恢复(HAL 层);PD 上限的降载动作(§8.3);CH224A 读到 100 W 与早上记的 20V/3A 不一致,待核。

本次新增/修改的文件

  • main/ntc.{h,c} 新(宿主机可测)— mV → Ω → 查 Murata NCP18XH103F03RB 的 R-T 表(−40~125 °C、5 °C 一格、格内线性插值); 贴 +3V3 / 贴地 / 表外一律「读不到」(⇒ t_thermal 满速)
  • main/thermal_esp.{h,c} 新(只进 IDF)— ADC1 oneshot + 曲线拟合校准(8 次平均,引脚反查通道);两个 PCNT 单元数 TACH 上升沿(累计计数、1 µs 毛刺滤波)
  • main/app_main.c — task_thermal 任务体(每 10 s 打一行温度 / mV / 占空比 / 转速);thermal_esp_init() + t_thermal_init() 放在上电恢复之前;cmd_env.thermal = &s_therm
  • main/CMakeLists.txt REQUIRES 加 esp_adc esp_driver_pcnt;host/CMakeLists.txt 加 ntc.c
  • test/test_ntc.c 新(4 例:表点、⭐方向「越热电压越低」、⭐开路/短路不是温度、比例式);版本 0.1.0-a16

上板实测(板 B,五槽空,风扇状态未知)

status: "temp":[38249,34027]   分压端 1266 / 1384 mV   ← 两路 NTC 读数合理(NTC1 在电感区更热)
        "fan":{"duty":300,"en":true,"rpm":[0,0],"stall":[true,true]}
events: [31, 14318, 0, 11(FAN_STALL), 0] [32, …, 11, 1]   ← 启动宽限 5 s + 一个窗口之后各报一次,不刷屏

踩到的坑(只写会再犯的)

  • 比例式 NTC 的电源误差估算:+3V3 偏 1 % 在 25 °C 附近是 ~0.6 °C(中点处电阻误差是电源误差的 2 倍、NTC 每度 ~4 %),不是 0.3 °C。
  • PowerShell 5.1 的 Set-Content -Encoding utf8 会写 BOM —— 改 phonerail.h 这种文件用 sed,别用它。
  • python 在 Git Bash 里是 Windows Store 占位程序,会挂住;一律用 /c/Python314/python。