文件
phonerail/firmware/HANDOFF.md
T
zhou yang和Claude Opus 5.5 c85eec53e6 固件 A15:启动顺序 + 降级矩阵(bringup.{h,c},已上板)
- 启动序列从 app_main.c 拆进 main/bringup.{h,c},宿主机可测:
  bringup_devices()(§10.9 第 1~4 步)→ 起 t_safety → bringup_power_restore()(第 5~6 步)
- 六片 INA226 写 Config/Calibration(之前没做,电流恒 0);输入侧 0x43 登记对调接
- 按「意图」逐路上电、错开 100 ms、每路等 PG 500 ms,等不到关回去并记 LOG_EV_PG_TIMEOUT(17)
- 意图只由 power 命令改(cmd_env_t.intent → NVS phonerail/rail_want)
- §10.10 逐行降级:INA/DAC/PCA9555/mux/PRSNT#/CH224A;mux 失联时不碰主干
- BOOT 事件 arg = 复位原因;HUB_RST# 仍只在上电复位时脉冲
- rail_volt_init() 一片失败不再放弃另一片;CH224A 主干 / 通道 5 两处都找
- sim:sim_gpio_rise_us / sim_gpio_set_hook,sim_gpio_drive 可在配置前调
- test_bringup.c 24 例 + test_cmd 意图 1 例,共 425 例全绿;版本 0.1.0-a15
- rack:事件表加 17 PG_TIMEOUT(已部署)

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

4.1 KiB
原始文件 Blame 文件历史

交接

更新:2026-09-27 完成 A15(启动顺序 + 降级矩阵,需求 §10.9 / §10.10)

一句话现状

启动序列从 app_main.c(只进 IDF、一行测不到)拆进 main/bringup.{h,c},宿主机 test_bringup.c 24 例逐个「拔掉」器件对 §10.10 逐行。 24 个 ctest、425 个用例全绿,idf.py build 通过(0xE2C60,分区剩 11%)。板 B(COM5)已烧 0.1.0-a15。

下一步

  • A16:风扇闭环接进 t_thermal 任务体(app_main.c 的 task_thermal 还是空壳;cmd_env.thermal 仍是 NULL)。
  • 服务器:rack/backend/prrack/protocol.py 已加事件 17,已部署(HOST=10.5.5.13,26 例过)。
  • 待核:CH224A 读到 5000 mA(100 W),而 PROGRESS 早上记的是 20V/3A —— 换了充电器,还是 0x50 的理解有误?

本次新增/修改的文件

  • main/bringup.{h,c} 新 — 两段:bringup_devices()(§10.9 第 14 步 + 降级)、bringup_power_restore(want)(第 56 步)
  • main/app_main.c — 启动段换成两段调用;t_safety 在两段之间 spawn(上电时巡检已在看); evlog_init_ex(esp_reset_reason()) 挪到最前;NVS 键 phonerail/rail_want 存「意图」;hub_reset_pulse_once() 搬进 bringup.c
  • main/cmd.h / cmd_exec.c — cmd_env_t 加 intent 回调,只有 power 命令真的生效时调
  • main/evlog.{h,c} — evlog_init_ex(boot_arg);新事件 LOG_EV_PG_TIMEOUT = 17
  • main/rail.{h,c} — rail_volt_init_one(addr);rail_volt_init() 一片失败不再放弃另一片
  • sim:sim_gpio_rise_us()、sim_gpio_set_hook();sim_gpio_drive() 可在配置前调、跨 config 保持(刀片把 PRSNT# 短到地与固件何时配脚无关)
  • test/test_bringup.c 新(24 例);test_cmd.c +1(意图);test_evlog.c 冻结号 +17;版本 0.1.0-a15

§10.10 各行落在哪

行 行为 用例
刀片 INA226 无应答 照常上电、blind、I2C_LOST(rail, 0x40) test_row_rail_ina_missing_keeps_power
DAC 无应答 不关输出、另一片照样初始化、影子回 3.90 test_row_dac_missing_…
PCA9555 无应答 照常上电,PG 改按 INA226 电压;两样都看不见 = 开着报 unverified test_row_pca_*(3 例)
mux 选不中 脉冲一次 MUX_RST#,仍不通 ⇒ 一路不开、MUX_LOST,不碰主干 test_row_mux_*(2 例)
PRSNT# 高 不发一个总线字节、不上电;想开的才记 SLOT_EMPTY test_row_empty_slot_*(2 例)
CH224A 读不到 / 偏低 按 60 W / 按读到的,PD_LIMIT 事件 test_row_pd_* + 通道 5 兜底
看门狗复位 BOOT.arg = 复位原因 test_row_watchdog_reset_is_recorded_in_boot
I²C 总线挂死 ⛔ 没做(9 个时钟恢复在 HAL 层) —

注错验证过:删掉 ina226_set_reversed(0x43) ⇒ 第一条红;错开改成 1 ms ⇒ 两条红。

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

status: "fw":"0.1.0-a15","in":{"mv":12034,"ua":98500}   ← 输入电流第一次是真值(以前 Calibration 没写,恒 0)
events: [27, 51, 0, 1(BOOT), 11(ESP_RST_USB), …]  [28, 155, 0, 16(PD_LIMIT), 0, 1000(=100 W), 5000 mA]

没有 I2C_LOST ⇒ 两片 DAC / 输入侧 INA226 / CH224A 都在主干应答。复位原因是 USB ⇒ 没碰 HUB_RST#,COM5 没掉。 上电复位路径(Hub 脉冲、DAC NVM 核对)和有刀片时的逐路上电还没在实物上走过——要等刀片 + 手机上架。

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

  • ⛔ mux 死了主干也够不着:i2cbus_xact(TRUNK) 先写 mux「全关」,失败就不跑回调。别以为「DAC 在主干上就不受 mux 影响」。
  • sim 里同一地址在主干和某通道各挂一个,主干那颗 present=false 时仍会先被匹配 ⇒ NAK。测「只在通道 5」要主干上干脆不挂。
  • 设定电压不持久化:热重启后五路回到 3.90 V(bringup 把 DAC 重写成安全值)。上位机要的话重下。
  • python 在这台机器的 Git Bash 里是 Windows Store 占位程序,会挂住;一律用 /c/Python314/python。