文件
phonerail/site/docs/index.md
T
zhou yang和Claude Opus 5 2bfe308b30 初始导入:PhoneRail 五路手机直供电源板
原理图/PCB 已在 EasyEDA 里做到 12 页跨页 0 漏接,固件刚完成骨架包 A1。
这次是把已有的一切一次性纳入版本控制,没有改动任何设计内容。

纳入:
- 设计与需求文档、PROGRESS.md、小米8 参考原理图 PDF 与追脚脚本
- .claude/ 下的 EasyEDA 桥接工具链与几何/网表缓存(eda-parts.json、
  pcb-parts.json、pcb-pads.json、p2-ch1.json 等,是重画各页的唯一事实来源)
- 117 张验证截图(本项目所有方向问题都是靠人眼看截图发现的,属于证据不是垃圾)
- firmware/ 的 A1 骨架与 site/ 文档站源码

.gitignore 排除:构建产物(firmware/build、host/build、sdkconfig)、
site/node_modules、__pycache__、桥接日志 _bridge.log、脚本自标的 *.stale。

.gitattributes 默认 `* -text`:现有 .py/.json 大多是 CRLF,原样存,
不让 git 重写行尾。唯一例外是 *.sh 强制 LF —— 带 \r 的 shell 脚本 bash 跑不了。

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QYuExfgyYa6DzRRcUso8M8
2026-09-06 18:18:14 +08:00

46 KiB
原始文件 Blame 文件历史

五路手机直供电源板 —— 项目需求文档

项 值
文档版本 v1.2(2026-09-06)—— 上位机链路定稿为方案 C(WiFi 常态 + USB CDC 兜底),回填 §10.8,新增 D5a / SW-12 / IF-19 与两条验收
v1.1 —— 新增 §10 软件架构设计,原 §10~§14 顺延为 §11~§15
项目代号 PhoneRail
对应设计文档 五路直供电源板设计.md v1.6 及其后续增补(§22 起的两板架构)
状态 需求已冻结;硬件处于 PCB 布线阶段(见 PROGRESS.md)

本文档与设计文档的分工 本文只回答 「要做成什么样、凭什么算做到了」; 「怎么做到」 一律在 五路直供电源板设计.md 里,本文只给条目号交叉引用。 两者冲突时:电气数值以设计文档为准(它是逐项算过并对过 datasheet 的), 需求的取舍与验收标准以本文为准。 设计文档 §0.1 的 13 条决策已定稿,本文把它们表述成需求,不重新讨论。 唯一的例外是 §10 软件架构设计 —— 那是「怎么做」,但固件在设计文档里没有落脚点, 暂放本文,理由写在该节开头。


1. 背景与目标

1.1 要解决的问题

手机农场里成排运行的小米8(dipper)主板,用原装电池供电有三个绕不开的问题:

  1. 电池会老化、会鼓包,几十台规模下变成持续的维护负担和安全隐患;
  2. 手机卡死时没法远程恢复 —— 人必须跑到机架前拔电池 / 长按电源键;
  3. 充电管理系统一直在工作,长期 100% 电量反而触发系统的异常逻辑。

1.2 项目目标

做一块电池位直供的电源板:拆掉电芯与保护板,从主板电池座直接灌一个受控的、 稳定在正常锂电范围内的电压;同时把「断电重启、按键模拟、进 Fastboot / 9008、 USB 通断」这些原本要人手做的动作全部电气化,交给板上 MCU 远程执行。

一句话验收目标:五台小米8 主板挂在这套板子上连续跑 24 小时无异常重启, 任何一台卡死时都能在不到机架前的情况下恢复到正常运行状态。

1.3 目标用户与使用场景

用户 场景
农场运维 日常挂机;某台无响应时下发一次重启;查某台的电流曲线定位接触不良
刷机 / 开发 远程进 Fastboot 或 9008(EDL) 刷包;有线 adb 抓日志
本项目自身 首板调试、长稳测试、失效注入验证

2. 范围

2.1 交付范围(In Scope)

# 交付物
D1 下板(电源板):12V 输入 → 五路 4 A 直供 + eFuse + 遥测 + ESP32-S3 控制
D2 上板(载板):五块主板的机械承载 + 板载 USB Hub + VBUS 开关 + 侧键顶针 + EDL 口
D3 两板对插的板对板接口(两条 2×20 排针,共 80 针)
D4 手机侧线束与离板电容组(电池排线改造、尾插 USB 线、EDL 引线)
D5 ESP32-S3 固件(遥测、两级重启、按键 / EDL 模拟、VBUS 通断、风扇闭环、告警)
D5a 双链路命令接口(2026-09-06 用户拍板):WiFi 为常态、USB CDC 为兜底,两条链路共用同一套命令语义。上位机侧的调用方由农场既有系统实现(N7),本项目交付板侧协议与实现,见 §10.8
D6 完整原理图(11 页)+ 两块 PCB + BOM + 首板调试与验收记录

2.2 明确不做(Out of Scope)

# 不做 理由
N1 电池充放电管理、模拟真实电池阻抗 直供不需要,电芯已移除
N2 支持 1S 以外的机型 / 非小米8 主板 全部机械与引脚定义都是 dipper 专用(§13)
N3 自制 USB-C 尾插转接板 决策 10:装原厂尾插小板,口温 NTC / CC / ESD / 天线馈点全在上面
N4 USB PD / BC1.2 协商,接快充充电器 决策 11:上游只接电脑 / Hub,VBUS 恒 5 V
N5 把过流保护做进 MCU 实时环路 那是 eFuse 的职责(SR-3)
N6 五路 Buck 错相同步 §8.4 已否决:器件离散度远大于想制造的相位差
N7 上位机管理软件 / Web 界面 本期只交付固件与命令接口,上层由农场既有系统对接

3. 系统组成(需求视角)

12V/10A 适配器
      │
 ┌────┴─────────────── 下板(电源 + 大脑)────────────────────┐
 │ 输入保护 → 五路独立 Buck → eFuse → 分流检测 → 输出          │
 │ ESP32-S3 + DAC ×2 + INA226 ×6 + 74HC595 ×3 + PCA9555        │
 │ 侧键驱动管 ×15 · 风扇驱动 · 辅助 3V3 / 5V                   │
 └────┬──────────── 2×20 排针 ×2(无高速信号)─────────────────┘
 ┌────┴─────────────── 上板(载板)────────────────────────────┐
 │ 5 × 小米8 主板(NPTH 定位孔 + 尼龙立柱)                     │
 │ USB2517I 7 口 Hub + 上游 USB-C + VBUS 负载开关 ×5            │
 │ 侧键顶针 ×15 · EDL 模拟开关 ×5 · P+/P− 焊盘 + 电容组 ×5      │
 └──────────────────────────────────────────────────────────────┘

两板之间保留 13 mm 缝,既是装配空间也是散热风道。


4. 功能需求(FR)

ID 需求 优先级 设计出处
FR-1 同时为 5 台小米8 主板供电,各路电气独立(独立回流地,不在手机端共地) 必须 §1 / §6.4
FR-2 每路输出电压可独立微调,调节在正常锂电范围内进行,步进优于 1 mV 必须 §4
FR-3 每路可独立硬断电并主动放电,实现真正意义上的「拔电池」 必须 §7
FR-4 每台手机可模拟 3 个侧键(PWR / VOL+ / VOL−),支持组合键 必须 §13.3
FR-5 每台手机可远程进入 EDL(9008) 模式 必须 §22.4
FR-6 每台手机的 USB VBUS 可独立通断,默认断开 必须 §15.1
FR-7 对外只用一根 USB 线,五路下行由板载 Hub 分 必须 §15.1
FR-8 每路可实时读取输出电压与电流;整板可读取输入电压与电流 必须 §8.2
FR-9 上报每路 eFuse 故障、电源好(PG)等状态 必须 §8.2
FR-10 主动风冷,风扇转速可调、可检测「有风扇停转」 必须 §22.6
FR-11 记录过流 / 故障事件(哪一路、何时、多大电流) 高 §8.3
FR-12 模拟电量曲线,避免系统因「电量永远 100%」触发异常逻辑 中(可选) §8.3
FR-13 板级温度监控,超阈值先降流再关路 高 §8.3
FR-14 整板功率预算,超过适配器能力时按优先级降载 中 §8.3
FR-15 调试口不依赖外部转串口芯片,插上 USB-C 即可下载与看日志 必须 §8.1

4.1 崩溃恢复流程(FR-3 / FR-4 的组合,本项目的核心价值)

固件必须实现两级重启,且先软后硬:

级 动作 触发条件 要求
一级(软) 长按电源键 ≈10 s adb 探活连续失败 N 次,或电流曲线卡死 优先使用,对闪存和文件系统友好
二级(硬) EFUSE_EN ↓ → 放电 → 等 3~5 s → EFUSE_EN ↑ 一级无效 输出必须真的掉到 <0.5 V,不能靠自然放电

为什么二级必须有主动放电:手机侧 2200 µF 配 ≈50 µA 关机待机电流,自然放电到安全 电压要 154 秒,「断电 10 秒」根本不触发重启。见 §7.1。


5. 电气与性能需求(PR)

ID 参数 要求 出处
PR-1 输入电压 12 V ±10%,成品适配器 §1
PR-2 输入电流 ≤ 8 A(含风扇 ≈8.3 A),建议配 12 V / 10 A(120 W) §1 / §22.6
PR-3 输出路数 5,彼此独立不共地 §1
PR-4 输出电压范围 3.52 ~ 4.01 V 连续可调 §4.3
PR-5 硬件电压上限 标称 4.01 V,最坏容差 4.12 V,软件无法越过 §4.4
PR-6 电压设定分辨率 12 位 DAC 微调,步进 ≈0.12 mV §4.5
PR-7 输出电流 4 A / 路(峰值);手机常态 0.3 ~ 1 A §1
PR-8 输出纹波 < 20 mVpp(板端测试点) §1
PR-9 开关频率 480 kHz,五路统一,不错相 §1 / §8.4
PR-10 整板功率 峰值 80 W(不会发生);常态 10 ~ 25 W §1
PR-11 电流测量分辨率 ≥ 0.5 mA(5 mΩ 分流 + Kelvin 四线) §8.2
PR-12 负载阶跃响应 0→4 A 阶跃(带 20 cm 线 + 电容组)压降 < 300 mV,无 6 kHz 振铃 §6.2
PR-13 满载温升 4 A 连续 30 min,电感 / IC 温升 < 40 K §11
PR-14 断电放电时间 EFUSE_EN ↓ 后 200 ms 内输出 < 0.5 V §7.2
PR-15 上电斜坡 缓启动 0.36 V/ms,涌流 ≤ 0.8 A;EN↑ 到稳定 ≈17 ms §5

5.1 输出上限为什么定在 4.01 V(这条需求的来源)

去掉原厂保护板后,输出上限由 1S 锂电端子的绝对上限 4.45 V 反推,而不是由保护板决定。 4.01 V 这个数字不是「够用就行」,是为了给 eFuse 的过压跳闸窗口让开 86 mV —— 若按早期的 4.22 V,第一层的最坏输出(4.34 V)会和 eFuse 的最坏跳闸下沿(4.206 V)重叠, 坏角落下 DAC 失效会误跳保护。详见 §5 的容差窗口分析。

因此 PR-4 / PR-5 是安全需求的一部分,不得为了「多给一点电压」而放宽。


6. 安全需求(SR)—— 本项目最高优先级

必须记录的失效模式:直供电最致命的失效不是固件写错电压值,而是 反馈分压的下电阻开路 → FB = 0 V → Buck 满占空比 → 输出直接跳到 12 V。 软件对此完全无能为力。 全部安全需求都要围绕这一条来读。

ID 需求 出处
SR-1 三层保护彼此独立:任何一层单独失效都不得导致手机损坏 §5
SR-2 第一层 · 拓扑限幅:分压网络与 DAC 量程在物理上把输出限死在 3.42 ~ 4.12 V(含最坏容差),全部落在正常锂电电压内。防固件 bug / I²C 误码 / MCU 跑飞 §4
SR-3 第二层 · eFuse 独立过压断开(每路一颗,最后一道硬件防线):OVP 4.36 V 标称、断开而非钳位、响应 2 µs;限流 4.45 A 恒流、不依赖 MCU §5
SR-4 eFuse 的过压响应必须来得及:按最坏值(Buck 高侧限流 14 A、负载 2200 µF)核算,余量 ≥ 10 倍 §5
SR-5 第三层 · 软件监控:电压偏离设定 >±100 mV 且持续 20 ms → 拉低该路 EN 并上报。仅承担记录与告警,不承担实时保护 §5
SR-6 复位安全:ESP32 复位 / 上电期间,五路输出全关、五路 VBUS 全断、15 路按键全不按、5 路 EDL 全不触发、风扇不转。靠上下拉电阻保证,不靠固件 §8.1 / §22.4
SR-7 放电 MOS 与 eFuse EN 硬件反相联锁,物理上不可能同时导通 §7.3
SR-8 输入保护:保险丝 + TVS + P-MOS 反接保护 §2
SR-9 12 V 母线泄放:母线 >13.2 V 时导通泄放,防 USB 反灌或突卸能量抬高母线 §15.2
SR-10 USB 反灌三条对策全做,一条都不能省:① 软件关充电 ② VBUS 负载开关 ③ 母线泄放 决策 12 / §13.5
SR-11 上游 USB 不做 PD 协商(CC 双 5.1 kΩ 下拉,纯 UFP),杜绝 VBUS 被抬到 9 / 12 V §15.1
SR-12 五台手机的地不得在载板上并成一根:定位孔做 NPTH,立柱用尼龙 §25.2
SR-13 固件不得提供任何能让输出超过 4.2 V 的接口 §8.3
SR-14 任一路输出不得给 ESP32 供电(用独立的 12 V→3.3 V 小 Buck) §8.3
SR-15 电源必须接原厂排线的 P+/P−(保护板输出侧),不是 B+/B− 决策 6 / §13.5

⚠️ SR-15 是最容易在装配环节做错、且常温下完全测不出来的一条。 焊在 B+/B− 时一切表现正常,只有过压时才暴露 —— 那时保护板仍串在通路里。 判别与验证步骤见 §13.5 / §13.7,已列为打样前阻塞项(V-1)。

⚠️ J600 的 GND3/GND4 固定脚实际接的是 VBATT,J1401 的 GND2 是 USB_VBUS。 按名字当地用会直接短路电池。


7. 接口需求(IF)

编号只增不改:新增接口一律取下一个空号,位置按逻辑归类 —— 所以表内序号不一定连续(如 IF-19 排在 IF-14 后面)。ID 是稳定的引用标识, 不是目录序号;改动已有编号会让所有交叉引用与验收记录失效。

7.1 手机侧接口(每台一套)

ID 接口 要求 出处
IF-1 供电 原装 BM3E 电池排线的 P+/P− 焊点;保留 BTB 公座 / NTC / ID,旁路保护板;电芯移除 §13.2 / §13.5
IF-2 侧键 J601(VOL+) / J602(VOL−) / J603(PWR) / J604(公共地),对地短接方式,绝不从外部灌电压 §13.3
IF-3 EDL 短接主板上的 TP1204 ↔ TP1205(1.8 V / 1 mA),用模拟开关,不用普通 N-MOS §22.4
IF-4 USB 装原厂尾插小板,本板只接 VBUS / D± / GND 四根 决策 10 / §15.1
IF-5 离板电容组 每路 2200 µF 普通铝电解(靠 ESR 阻尼)+ 100 µF ×2 + 22 µF ×2 + 100 nF,必须装在排线端,不在电源板上 §6.3
IF-6 线缆 ≤ 20 cm、18 AWG 或更粗、正负双绞或紧贴平行;板端用 Micro-Fit 3.0 / XT30,不用杜邦线 §6.4

⚠️ IF-5 的 2200 µF 千万不能买成聚合物电容。 整个阻尼设计靠的就是普通铝电解那 几十 mΩ 的 ESR;换成 12 mΩ 的聚合物,Q 从 0.19 跳回 4.5,线缆 LC 会在 6.2 kHz 上振铃。

⚠️ IF-5 的大电容必须在排线端。 放在电源板上等于隔着 300 nH 的线缆电感,基本无效。

7.2 板对板接口

ID 需求 出处
IF-7 两条 2×20 排针(共 80 针),分列板子两端 §22.2 / §25.10
IF-8 一根高速差分都不穿连接器 —— Hub、上游 USB-C、VBUS 开关全部上移到载板 §22.1
IF-9 排针只走电源与低速控制;每路 P+/P− 独立分配针位,保证独立回流(FR-1) §22.2
IF-10 两板间净空 13 mm;载板底面元件与下板高元件的高度预算必须逐点核过 §26.2

7.3 对外接口

ID 接口 要求
IF-11 电源输入 DC 12 V 插座(XT30 级),配 10 A 适配器
IF-12 上游 USB 载板 USB-C(UFP),一根线接电脑
IF-13 调试 USB 下板 USB-C,ESP32-S3 原生 USB-Serial-JTAG;VBUS 故意不接(物理上杜绝反灌 3V3)。同一个口兼作 SW-12 的兜底命令链路(原生 USB-Serial-JTAG 本身就是 CDC-ACM,不影响 esptool 下载),分帧要求见 §10.8
IF-14 风扇 5 × KF2510-3A(+12 V / 回流 / TACH)
IF-19 控制网络 WiFi(ESP32-S3 板载,无需增加器件),SW-12 的常态命令链路。凭据与服务端地址存 NVS,不编译进固件 —— 新板上架时先用 IF-13 的 USB 链路配网

⚠️ IF-12 与 IF-13 是两个长得一样的 USB-C,插错的现象是「adb 整排不见」, 很难联想到是插错口。丝印必须写清楚,建议用不同颜色座子或在外壳上做标记。

7.4 内部数字接口

ID 需求
IF-15 I²C 单条总线挂 10 个器件:INA226 ×6(0x40/41/44/45/42/43)、DAC63204 ×2(0x4A / 0x4B)、PCA9555(0x20)、LM75BD(0x48),地址互不冲突
IF-16 ⚠️ INA226 的通道号 ≠ 地址低位(为布线让路重排过),固件必须查表,不能算
IF-17 74HC595 ×3 级联成 24 位移位链:15 路侧键 + HUB_RST + 5 路 EDL_EN;先移入的字节落在 U33 上
IF-18 EFUSE_EN ×5 与 VBUS_EN ×5 必须 GPIO 直连,不得经移位寄存器 —— 安全关键,故障瞬间要能立刻关断

8. 机械与热需求(MR / TR)

ID 需求 出处
MR-1 载板 220 × 135 mm,四角 R5;五块主板 3+2 双排面对面,第二排居中 §25.1
MR-2 下板 160 × 125 mm,装配时相对载板原点偏移 (30, 5) §25.2
MR-3 每台手机 7 个定位孔,全部 NPTH Φ2.5 + 尼龙立柱(见 SR-12) §25.2
MR-4 侧键用顶针接触,顶针焊盘必须避免把相邻触点短路 §25.3
MR-5 排线穿槽:电池排线 8×38 → 槽 10×3.0;尾插排线 18×55 → 槽 20×3.0(在 J1401 正下方) §25.16
TR-1 总热负荷 ≈25 W(5×SDM845 满载 10~15 W + 下板功率级 ≈9 W) §22.6
TR-2 强制风冷 4 进 1 出 = 机箱正压(灰尘往外走);两板间 13 mm 缝作天然风道 §22.6
TR-3 所需风量仅 ≈2.9 CFM,风量不是瓶颈,风道与正压才是设计要点 §22.6
TR-4 风扇 5 × 12 V ≈0.70 A;低边 N-MOS + PWM,漏极必须并续流二极管 §22.6
TR-5 风扇闭环的测温点放载板(测的是手机),不能用下板功率级的两路 NTC 做反馈 §22.6
TR-6 TACH 必须分压后再进 GPIO;⚠️ 低边调速下 PWM 关断期间读不到转速,固件需在导通窗口采样 §22.6

9. 固件需求(SW)

本节只列「固件要做到什么」。怎么组织成一份固件见 §10 软件架构设计。

9.1 必做

ID 需求
SW-1 崩溃检测 + 两级自动重启(§4.1)—— 整块板子最核心的价值
SW-2 20 ms 周期巡检六路 INA226,电压偏离 >±100 mV 持续 20 ms 即关路告警(SR-5)
SW-3 过流 / 故障事件记录:路号、时刻、电流值 —— 排查排线接触不良的唯一线索
SW-4 单路电压微调接口(跑不稳的手机提到 4.0 V,或反向降压降温),上限受 SR-13 约束
SW-5 侧键序列:短按 100 ms 唤醒 / 长按 2 s 开机 / 长按 10 s 强制重启 / VOL−+PWR 进 Fastboot / VOL++PWR 进 Recovery
SW-6 EDL 时序固定为 EDL_EN=1 → VBUS_EN=1 → 等枚举 → EDL_EN=0(先短接再插 USB)
SW-7 开机脚本执行「关充电」(写 input_suspend 类节点),路径需在首台机上确认后写死
SW-8 USB 反灌保护:检测到该路电流转负或母线上升,200 ms 内断开该路 VBUS
SW-9 风扇 PWM 闭环(以载板 LM75BD 为反馈)+ TACH 停转告警
SW-10 整板功率预算:读输入侧 INA226,超适配器能力时按优先级降载
SW-11 上电默认全关:五路输出关、VBUS 断、按键不按、EDL 不触发
SW-12 双链路命令接口:WiFi 为常态、USB CDC 为兜底,两条同时在线、共用同一套命令语义与同一个命令处理器;命令带全局序号做幂等判重。链路失联不触发任何动作。架构见 §10.8

9.2 明确禁止

ID 禁止事项 理由
SW-N1 让 ESP32 参与过流保护的实时环路 那是 eFuse 的活,MCU 不够快也不够可靠
SW-N2 提供任何能让输出超过 4.2 V 的接口 SR-13
SW-N3 烧写 DIS_USB_JTAG eFuse 烧了之后引脚 JTAG 和 USB 两边都进不去,板上没有 JTAG 排针
SW-N4 把 INA226 通道号当地址算 IF-16

10. 软件架构设计

这一节为什么在需求文档里:本文原则上只讲「做成什么样」,但固件在设计文档里没有 落脚点 —— 设计文档 §8.3 只有一张按价值排序的功能清单,没有结构。在补出一份独立的 软件设计文档之前,架构先放这里,与 §9 的固件需求贴在一起看。 硬件的「怎么做」仍然一律在设计文档。

10.1 分层与职责边界

┌─ 农场管理系统(既有,本项目不交付 —— N7)────────────────────────┐
│   adb 探活 / 业务调度 / 崩溃判定                                  │
└───────┬────────────────────────────────┬──────────────────────────┘
        │ adb over WiFi(业务面)         │ 控制面(10.8,⚠️ 链路待定)
        ▼                                ▼
   5 台小米8 主板                  ┌─────────────────────┐
        ▲                          │  PhoneRail 控制器    │
        │ 供电 / 侧键 / EDL / VBUS  │  ESP32-S3 固件       │
        └──────────────────────────┤  遥测 · 执行 · 记录  │
                                   └──────────┬──────────┘
                                              │ 只能建议,不能否决
                              ┌───────────────▼───────────────┐
                              │ 硬实时层:eFuse OVP / 限流      │
                              │ 放电 MOS 反相联锁 / 上下拉      │
                              │ —— 不含任何软件(SR-3、SR-7)   │
                              └───────────────────────────────┘

一条边界决定了下面所有取舍:固件是遥测 + 执行器 + 记录仪,不是保护装置 (SR-5、SW-N1)。凡是「必须及时」的事都已经在硬件里了;固件里没有任何一条路径 是「不跑到就会烧手机」的。因此:

  • 任务优先级不需要为保护让路,只需要保证遥测不被执行器序列饿死;
  • 看门狗复位是可接受的失效(复位即全关,SR-6),不需要为了「保持输出」而弱化看门狗;
  • 固件可以随时被重启、被降级运行,硬件安全性不变。

10.2 架构的第一个判断:失联 ≠ 断电

状态 输出该怎么办 为什么
ESP32 复位 / 上电中 全关(硬件下拉保证,SR-6) 状态未知,且此刻手机本来就没在跑
与上位机失联 保持供电不动 五台手机正在跑业务;因为控制链路断了就把它们全断电,是把一次网络故障放大成一次全场停机
本地判据触发(SR-5 / SW-8 / 过温) 关对应那一路 已知的危险,且范围可控

⚠️ 这三行看起来像常识,但它们互相矛盾过一次:「安全默认值 = 关」只对未知状态成立。 失联是已知状态,此时最安全的动作是「什么都不做」。固件里不要写「心跳超时就关输出」。

推论:失联期间固件必须能独立运行全部本地职责 —— 巡检、风扇闭环、事件记录、 按队列执行未完成的序列。上位机回来之后靠事件日志补齐时间线(10.7)。

10.3 任务划分(FreeRTOS / ESP-IDF)

任务 周期 优先级 职责 失败后果
t_safety 20 ms 最高 读 6 片 INA226(V+I)与 PCA9555 输入;执行 SW-2 / SW-8 判据;越界直接操作 EFUSE_EN / VBUS_EN(GPIO 直连,不经任何队列或抽象层) 告警延迟;保护本身不受影响(eFuse 是硬件)
t_thermal 1 s 中 两路 NTC(下板功率级)+ 载板 LM75BD(手机侧)→ 风扇 PWM 闭环;过温先降流后关路(FR-13、TR-5) 风扇维持上一个占空比
t_actuator 事件驱动 中 每路一个状态机:断电重启 / 按键序列 / EDL 序列(10.6) 序列停在中间 —— 必须有超时兜底
t_link 事件驱动 低 上位机命令解析与遥测上报(10.8) 见 10.2:不影响本地职责
t_log 空闲 最低 环形缓冲落盘(10.7) 丢日志,不丢功能

共享资源只有两个,各配一把互斥锁:

  1. I²C 总线 —— 10 个器件在同一条上(IF-15),其中 LM75BD 还在排针另一侧的载板上。
  2. 74HC595 的 24 位链 —— 全板共享,见 10.6 的影子寄存器。

I²C 带宽核算(400 kHz,t_safety 是唯一的高频用户):

一次 INA226 寄存器读 ≈ 46 个位周期 ≈ 115 µs
6 片 × 2 个寄存器(总线电压 + 分流电压) = 12 次  ≈ 1.4 ms
PCA9555 读两个输入端口                          ≈ 0.12 ms
                                        合计 ≈ 1.5 ms / 20 ms = 约 8 % 占用

余量充足,t_thermal 和偶发的 DAC 写完全挤得下。首板上电时用逻辑分析仪实测复核一次 ——这个数是按理想时序算的,没算时钟延展和重试。

10.4 五路一张表:禁止用通道号算任何东西

这是本项目最容易写出「看起来对、实际错一路」的地方。三组编号都不是逻辑顺序:

  • INA226 地址按布线难度重排过(IF-16,设计文档 §8.2);
  • 74HC595 的位序按 PCB 几何排(设计文档 §17.2 / §22.4);
  • GPIO 编号按出线方向倒推(设计文档 §26.18)。

所以固件里只允许有一张静态配置表,全部五路循环都索引它:

typedef struct {
    uint8_t  ina_addr;      /* 0x40 0x41 0x44 0x45 0x42 —— 查表,不能算 */
    uint8_t  dac_chip;      /* 0x4A: CH1-3   0x4B: CH4-5 */
    uint8_t  dac_ch;        /* U6.OUT0/1/2   U7.OUT0/1  */
    gpio_num_t efuse_en;    /* GPIO 直连 */
    gpio_num_t vbus_en;     /* GPIO 直连 */
    uint8_t  key_bit[3];    /* PWR / VUP / VDN 在 24 位链里的位号 */
    uint8_t  edl_bit;       /* U33 上的位号 */
    uint8_t  flt_bit;       /* PCA9555 IO0_0..4 */
    uint8_t  pg_bit;        /* PCA9555 IO1_0..4 */
} rail_cfg_t;

⚠️ ina_addr = 0x40 + ch 这行代码一定会被写出来,而且只有 CH3/CH4/CH5 是错的。 实际地址是 0x40 / 0x41 / 0x44 / 0x45 / 0x42。查表,不要算。

同理,PCA9555 的方向寄存器只能配成全输入:备用脚 Port0[7] / Port1[7:5] 在硬件上 直接接地,配成输出并写 1 就是对地短路(设计文档 §17.2 已在图纸上注明)。

10.5 电压通道:DAC 只做微调,而且是反向的

事实 含义
Vd = 0 V → 输出 4.010 V(上限) DAC 写得越大,输出越低
Vd = 0.548 V → 输出 3.90 V(NVM 出厂默认) 上电即安全值,不依赖 ESP32 初始化成功
Vd = 2.424 V(满量程)→ 输出 3.524 V(下限) 满量程是 2.424 V,不是 2.5 V(内部基准 1.212 V ×2)

⚠️ 反向关系是本节最容易写反的一条。 写反的现象不是报错,而是 「调高电压的命令把手机调到了 3.52 V」——手机照样能开机,只是更容易在负载尖峰下掉电, 而且要跑一阵子才看得出来。固件里把这一步封成 rail_set_mv() 单一入口, 内部做 mV → Vd → code 的换算,不要在别处直接写 DAC 码值。

三条固件规矩:

  1. 越界即拒绝:rail_set_mv() 收到 >4010 mV 的请求直接返回错误并记事件(SR-13)。 注意这是第四道限制,前三道在硬件里 —— 它的作用只是让操作者早点知道自己写错了。
  2. 不用 DAC 做保护:任何时候都不要靠「把电压调低」来处理异常,那是 EFUSE_EN 的活。
  3. 出厂标定:分压网络与 DAC 基准都有 ±1 % 级的容差,用该路 INA226 读回实际输出, 做一次两点线性标定存进 NVS。标定值缺失时退回理论公式(误差约 ±40 mV,可用)。

10.6 执行器:三个状态机 + 一个影子寄存器

每路三个序列,彼此互斥、不可重入(同一路上同时只能跑一个):

序列 时序 关键约束
硬重启 EN↓ → 等 3~5 s → EN↑ → 等 17 ms(tON 5.1 ms + 缓启动斜坡 11.5 ms)→ 等 PG 置位 放电由硬件联锁自动完成(SR-7),固件不要去控制放电 MOS
按键 置位 → 保持 T(100 ms / 2 s / 10 s)→ 清零 组合键(VOL−+PWR)必须同一帧写进去,不能先后两次
EDL EDL_EN=1 → VBUS_EN=1 → 等枚举 → EDL_EN=0 顺序固定(SW-6):先短接再插 USB

影子寄存器是这一节的核心:15 路按键 + HUB_RST + 5 路 EDL_EN 全在同一条 24 位 移位链上,写任何一位都要把整条链重发一遍。

ESP32.KEY_SER → U21 → U22 → U33        (先移入的字节落在链尾 U33)
写入顺序:U33 字节 → U22 字节 → U21 字节,最后一个 RCLK 上升沿统一生效

规矩:内存里保存一份 24 位影子值,全固件只有一个函数能写 595,任何任务改按键 或 EDL 都是「改影子 → 请求刷新」。多处直接操作移位链,症状是另一台手机的按键被顺手 清掉,而且复现要靠两个动作正好撞在一起 —— 属于会拖很久的那类 bug。

RCLK 打点之前输出不变,所以整帧刷新是原子的;OE# 保持有效,不要用拉高 OE# 的方式「临时全松开」——那会让 15 个栅极同时进高阻,靠的是每个栅极自己的 100 kΩ 下拉, 是复位路径,不是正常控制路径。

10.7 事件记录与存储

事件是 SW-3 的交付物,也是排查排线接触不良的唯一线索,所以记录路径不能依赖上位机在线。

项 设计
缓冲 RAM 环形缓冲,≥256 条;t_safety 只入队,不落盘
落盘 t_log 空闲时批量写 NVS / SPIFFS 分区
单条 时间戳 + 路号 + 事件类型 + 当时的 V/I(16 B 量级)
容量 4096 条 ≈ 64 KB,按每天几十条算够存半年以上
时间 上电从 0 计;上位机连上后下发一次墙钟做偏移校正(不加 RTC 芯片)

必记事件:eFuse FAULT / PG 变化、SR-5 触发关路、SW-8 反灌断 VBUS、过温降载、 每次重启序列(软 / 硬、谁下的命令)、越界命令被拒、I²C 器件失联、风扇停转。

10.8 上位机接口 ✅ 已定稿(2026-09-06 用户拍板:方案 C)

这一节回答的问题:SW-1 的触发条件写的是「adb 探活连续失败 N 次」, 而 ESP32 跑不了 adb —— 所以崩溃判定必然发生在上位机,板子只负责执行动作。 这意味着必须有一条控制链路,而在此之前全部文档里都没有定过它。

结论:WiFi 为常态链路,USB CDC 为兜底链路,两条同时在线。

选它不是因为「都要」,而是因为 SW-1 是这块板子的核心价值, 而 WiFi 与手机 adb 走的是同一张网 —— 只做 WiFi 等于让「救援通道」和「故障通道」 共命运,恰好在最需要它的时候一起失效。USB 的增量成本很低:线本来就插着。

留档备查的两个单选方案:

方案 优点 为什么不单独用
A. 只做 WiFi 无线、可多台组网;设计文档 §9.5 的 3V3 预算里已经给 ESP32-S3 的 WiFi 突发留了 ≈350 mA,说明当初就是按带 WiFi 设计的 网炸了救砖通道跟着炸,见上
B. 只做 USB CDC 最可靠,不依赖网络 每块板占上位机一个 USB 口;机架规模上去之后不现实

两条链路怎么共存

        WiFi (MQTT/HTTP)          USB CDC (J22)
              │                        │
      ┌───────▼────────┐      ┌────────▼───────┐
      │ 传输适配器 A    │      │ 传输适配器 B   │   ← 只管收发字节与分帧
      └───────┬────────┘      └────────┬───────┘
              └──────────┬─────────────┘
                  ┌──────▼───────┐
                  │ 单一命令处理器 │   ← 全部鉴权、限幅、幂等判重都在这里
                  └──────┬───────┘
                         ▼
                    执行器 / 遥测

四条规矩:

  1. 命令处理器只有一个。 两条链路是传输,不是两套功能。任何安全约束 (SR-13 的限幅、越界拒绝、序号判重)都写在处理器里,绝不写进适配器 —— 否则以后加第三条链路时必然漏掉一处,而功能测试完全测不出来。
  2. 不做主备切换,两条都常开。 谁先送到算谁的,靠 3 的序号去重。 做「主备」就要判定"主链路死了没有",而那个判定本身就是新的故障点。
  3. 序号是全局的,不分链路。 上位机给每条命令一个单调递增的序号, 板子记住最近 N 个已执行的序号。WiFi 重传 + USB 又发了一遍同一条命令时, 第二次必须被丢弃 —— 否则「按 10 秒电源键」会执行两遍,第二遍正好按在刚开机的手机上。
  4. USB 链路与日志共用一条流。 ESP32-S3 的原生 USB-Serial-JTAG 本身就是 CDC-ACM,不需要切到 TinyUSB,也不影响 esptool 下载(FR-15 不变)。 代价是命令响应和运行日志在同一条串流上,必须分帧(建议命令用带前缀的单行 JSON,日志走另一个前缀),否则日志一刷就把响应冲散。

⚠️ 别把 WiFi 凭据和 MQTT 地址编译进固件。 放 NVS,用 USB 链路配置 —— 这正好是兜底链路的第二个用途:新板子上架时先插 USB 配网。

命令语义与链路无关,两条链路完全一致:

命令 参数 说明
status — 五路 V/I/PG/FLT、输入 V/I、两路 NTC + 载板温度、风扇转速、各路状态机状态
set_voltage 路号, mV 走 rail_set_mv(),越界拒绝(10.5)
power_cycle 路号, 断电秒数 二级硬重启(4.1)
key 路号, 键位掩码, 保持 ms 单键与组合键同一个接口
edl 路号, on/off 内部按 SW-6 的固定时序展开
vbus 路号, on/off 默认断开
fan 占空比 / auto auto 交回 t_thermal 闭环
events 起始序号 增量拉取事件日志

三条接口硬约束:

  • 没有任何命令能让输出超过 4.2 V(SR-13)—— 包括「原始 DAC 写入」这类调试命令, 它压根不该存在于发布固件里。
  • 命令必须幂等或带序号:链路重传时不能让「按 10 秒电源键」执行两遍(上面第 3 条)。
  • 链路失联不触发任何动作(10.2):没有心跳超时关输出这回事。

10.9 启动顺序

1  上电:GPIO 全部显式置安全态(硬件下拉已保证,固件再确认一次)
2  I²C 扫描 10 个器件 ——  缺任何一个都进「降级模式」(10.10),不要照常启动
3  读回 DAC 通道值(NVM 默认 3.90 V),与期望比对
4  载入 NVS 里的标定值与上次的每路使能状态
5  逐路上电,**路与路之间错开 100 ms**
6  等各路 PG,超时则记事件并保持该路关闭
7  起风扇闭环,起链路任务

⚠️ 第 5 步的错开不是讲究,是必须:单路缓启动涌流 0.8 A,五路同时开就是 4 A 叠在 12 V 输入上,而输入预算本来就是 8.3 A(PR-2)。错开 100 ms 之后 各路的斜坡(11.5 ms)完全不重叠。

10.10 降级矩阵

失效 检测方式 行为
某片 INA226 无应答 I²C NAK 该路失去遥测 → 保持供电,标记为「盲跑」,禁用该路的 SR-5 / SW-8 判据并持续告警
I²C 总线挂死(SDA 被拉低) 连续超时 发 9 个时钟脉冲做总线恢复;仍不通则复位 I²C 外设;再不通进降级模式
DAC 无应答 I²C NAK 不关输出 —— DAC 不响应时输出停在 NVM 默认的 3.90 V,是安全值
PCA9555 无应答 I²C NAK 失去 FAULT / PG 可见性;改用 INA226 的电压判据兜底
载板 LM75BD 无应答 I²C NAK 多半是排针接触不良(它在排针另一侧)→ 风扇转到 100 % 并告警,不要按「读不到温度=不热」处理
上位机失联 心跳超时 见 10.2:什么都不做
看门狗复位 — 复位即全关(SR-6),重启后按 10.9 恢复,并记一条复位事件

降级模式的定义:只保留「关断能力」与「事件记录」,不再自动上电、不接受调压命令, 持续告警。宁可五台手机不开机,也不要在盲态下带电跑。

10.11 关于 FR-12「模拟电量曲线」的一个说明

这条需求的实现方式和它的字面意思不一样,值得在架构层写清楚:手机的电量计是从 电池端电压推算 SoC 的,我们给的电压就是它看到的全部信息。所以「模拟电量曲线」 = 按锂电放电曲线缓慢改变输出电压(比如 12 小时从 4.01 V 走到 3.60 V,再跳回去)。

两个后果:

  • 它不需要任何新硬件,是 rail_set_mv() 之上的一个慢速调度器;
  • 它与 SW-4(单路电压微调)共用同一个执行器,两者必须互斥 —— 否则运维把某台调到 4.0 V,曲线任务转头又把它拉回 3.6 V。

FR-12 是「中(可选)」,建议首版先不做,把接口留出来即可。

10.12 架构层面的待定项

项 状态
上位机链路选型(10.8) ✅ 2026-09-06 用户拍板:方案 C,WiFi 常态 + USB CDC 兜底
OTA 升级 既然定了 WiFi,建议做:双分区 + 失败回滚。没有 OTA 的话一次坏固件要把板子从机架上拆下来插 USB,而 USB 兜底链路本身也能烧 —— 所以这是「省事」不是「救命」,可以排在首版之后
WiFi 掉线重连策略 指数退避 + 上限;重连过程不得阻塞 t_safety(10.3),链路任务优先级最低就是为这个
时间同步 当前方案是上位机下发墙钟做偏移,不加 RTC。若日志要脱机长期归档需重议
FR-12 电量曲线 建议首版不做,只留接口(10.11)
input_suspend 节点路径 与 SW-7 / V-8 是同一件事,首台机上确认后写死

11. 约束与假设

11.1 硬约束

ID 约束
C-1 全部为 1S 机型,负载固定为小米8(dipper)主板
C-2 原厂电池保护板被旁路 ⇒ 失去一层与本板独立的防线,全部安全责任落在 SR-2 / 3 / 5 上
C-3 无电池 ⇒ 失去一个内阻只有几十 mΩ 的缓冲电容。瞬态阻抗设计(§6)比电压精度重要得多,是这类板子的主要故障来源
C-4 ESP32-S3-WROOM-1 可用 IO 有限(19 根信号已排满),新增功能只能走移位寄存器或 I²C 扩展
C-5 USB2517I 要求 D± 走线 ≤ 6 inch(152 mm) ⇒ Hub 只能放在载板通道正中
C-6 BM24(尾插)连接器只有 10 次插拔寿命 ⇒ 装配流程必须减少反复插拔
C-7 小米8 原理图 PDF 是第三方扫描件,一切引脚 / 机械结论以实测为准

11.2 假设(若不成立需重新评估)

ID 假设
A-1 上游 USB 恒为 5 V(只接电脑 / Hub,不接快充头)
A-2 手机关机待机电流在 ≈50 µA 量级
A-3 目标 ROM 上存在可写的「关充电」sysfs 节点(SW-7,路径待确认)
A-4 手机常态功耗 0.3 ~ 1 A / 路,五路同时 4 A 满载不会发生

12. 验收准则

12.1 首板上电验收(17 步,严禁第一次上电就接手机)

完整步骤与通过标准见设计文档 §11。其中:

  • 第 5 步(人为断开 R2,模拟致命故障) 与 第 6 步(负载阶跃 + 阻尼验证) 是这块板子的两个核心验证项,不得跳过 —— 它们分别验证 SR-3 和 PR-12 / C-3。
  • 第 12 步(ESP32 复位安全测试) 验证 SR-6。
  • 第 14 步(USB 反灌测试) 验证 SR-10 / SW-8。

12.2 需求 → 验收方法对照

需求 验收方法 通过标准
PR-4 / PR-5 扫 DAC 全量程 输出扫过 3.52 ~ 4.01 V,与公式误差 <1%;任何码值都到不了 4.2 V
SR-2 固件写越界值 输出被拓扑限死,不越过上限
SR-3 / SR-4 人为断开反馈下电阻 eFuse 断开,输出侧尖峰不超过 4.7 V
SR-5 注入 ±150 mV 偏差 20 ms 内关路并产生告警记录
SR-6 手动复位 ESP32 示波器确认五路立即关断、15 路按键无一误触发、EDL 无触发
SR-7 固件同时置位 EN 与放电 硬件互斥,10 Ω 上无持续功耗
SR-9 可调电源把母线升到 13.5 V 泄放导通并拉回 13.2 V 以下
SR-10 / SW-8 不关充电直接接 USB 电流转负 → 固件 200 ms 内断 VBUS
SR-15 排线加 4.40 V 不断开(断开说明焊到了 B+/B−)
PR-12 0→4 A 阶跃(带 20 cm 线 + 电容组) 压降 <300 mV,无 6 kHz 振铃
PR-13 满载 4 A 跑 30 min 温升 <40 K
PR-14 断电重启时序 输出 200 ms 内 <0.5 V
FR-4 / SW-5 逐项试按键 短按唤醒 / 长按 10 s 强制重启 / VOL−+PWR 进 Fastboot 均有效
FR-5 / SW-6 下发 EDL 序列 主机可见 9008 设备
FR-7 五台全接 adb devices 与 fastboot devices 均可见
FR-10 / TR-6 拔掉一个风扇 TACH 频率下降约 1/5,产生告警
SW-12 断开 WiFi(拔 AP / 关热点),从 USB 下命令 命令照常执行;五路输出不受影响(10.2 的失联行为)
SW-12 同一序号的命令从两条链路各发一遍 只执行一次,第二条被判重丢弃并记事件
总体目标 五台长稳 24 h 无重启、无告警

12.3 装配前必做的实物验证(阻塞项)

项 内容 出处
V-1 排线旁路验证:确认焊在 P+/P−,4.40 V 不断开 §13.7
V-2 侧键触点定位:万用表 5 分钟,拍照存档 §13.3
V-3 环路补偿实测扫频(三个位置已留焊盘) §9.2
V-4 量两个新连接器实物高度(XT30PW-M / 2510-3A)—— 余量只有 1~3 mm,别信估计值 §26.16
V-5 两条排线路径试装(电池 / 尾插穿槽走背面) §25.16
V-6 J7n 镜像位按底层装法复做;装好后做两点通断复核 §24.3 / §25.16
V-7 风扇线装配顺序:必须「先插五根风扇线,再合上载板」 §26.16
V-8 确认目标 ROM 上 input_suspend 的实际路径 §15.2

完整的待办 / 已关闭清单以设计文档 §12 为准,本表只列对需求验收有约束的。


13. 已知风险与已接受的取舍

# 风险 处置
R1 去掉原厂保护板 = 少一层独立防线 已接受。定量核算 eFuse 余量 ≈11 倍;且 eFuse 断开后 2200 µF 仍撑着,手机继续运行不掉电,表现优于保护板断开
R2 最坏角落下 eFuse 可能到 4.519 V 才跳,超 1S 上限约 60 mV 已接受。走到这一步说明第一层已失效,输出以 6.4 mV/µs 冲过这 70 mV 只需 ≈10 µs,远短于锂电过压损伤时间常数
R3 两个同款 USB-C 插错 已接受(用户在 USB-B / USB-C 之间选了 C)。靠丝印 + 颜色 + 外壳标记缓解
R4 低边调速导致 PWM 关断期间读不到转速 已接受。若最终选 4 线 PWM 风扇,MOS + 续流管 + 分压可全删
R5 IF-5 的 100 µF MLCC 在 3.9 V 偏压下只剩 ≈40 µF,中频储能从 200 µF 降到 ≈80 µF 待复核。严格照原方案需换真聚合物
R6 电感 SPM6530T-4R7M 的 Isat 6.2 A < 原定的 7 A 已接受,裕量分析见设计文档「已知遗留」
R7 BM24 仅 10 次插拔寿命 靠装配流程规避(C-6)
R8 手机主板机械固定方式(是否连中框)未定 不阻塞打样

14. 需求 → 设计追溯表(速查)

需求域 设计文档章节
规格 / 输入输出 §1、§3
电压范围与本质安全 §4(含 §4.4 失效态验算)
三层保护链 §5
瞬态阻抗与阻尼(C-3) §6
断电重启与放电 §7
MCU 接口 / GPIO / I²C §8、§26.18
选型与 BOM §9
PCB 与叠层 §10、§25、§26
验收与调试 §11、§14
手机侧接口 §13
USB 子系统 §15、§18、§21
两板架构与机械 §22、§25
散热 §22.6
EDL §22.4
软件架构 设计文档里没有对应章节 —— 见本文 §10

15. 术语

术语 含义
直供 拆掉电芯与保护板,从电池座直接供给受控电压
dipper 小米8 的代号
P+ / P− 电池保护板的输出侧焊点(本项目的接入点)
B+ / B− 电芯侧焊点(接错这里是本项目最隐蔽的装配错误)
eFuse 带可调过压 / 限流 / 缓启动的电子保险丝(TPS25940A)
EDL / 9008 高通紧急下载模式
本质安全 靠拓扑与元件取值在物理上限死危险状态,而不是靠软件判断
下板 / 载板 下板 = 电源板;载板(上板)= 承载五块手机主板的板