文件
phonerail/firmware/HANDOFF.md
T
zhou yang和Claude Opus 5 ceadf08345 A3:INA226 驱动 + 六片地址表
地址表按设计文档 §8.2 钉死(0x40/41/44/45/42 + 输入侧 0x43),只走
ina226_rail_addr(),并有一条测试专门拦「ina_addr = 0x40 + ch」这一手
(CH3/CH4/CH5 三路全错,需求 §10.4)。

驱动只经 hal_i2c_*:认件(MFG/DIE ID)、写 Config 0x4327 + CAL 2048 并
回读校验、读 V/I/分流/功率。电流有符号,反灌为负(SW-8 判据)。
巡检走 read_vi(),每片两次事务,对应 §10.3 的 8% I²C 占用。

两条留给下次的坑:寄存器指针不依赖自增(sim 会自增、真件不会,靠自增
在宿主机上测不出来);CAL 丢了不报错只让 Current/Power 恒读 0,所以
有 ina226_check()。

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

3.7 KiB
原始文件 Blame 文件历史

交接

更新:2026-09-06 完成任务包 A3(INA226 驱动 + 六片地址表)

一句话现状

六片 INA226 的地址表钉死在代码里(0x40/41/44/45/42 + 输入侧 0x43), 驱动能认件(MFG/DIE ID)、写 Config+CAL 并回读校验、读出 V / I / 分流 / 功率, 电流有符号(反灌为负)。4 条 ctest(34 个用例)全绿,idf.py build 通过。

下一步

A4:DAC63204 驱动 + rail_set_mv()(需求 §10.5 全节)。 三条断言:①4020 mV 被拒(SR-13)②写更大的码值输出更低(反向关系)③3900 mV ↔ Vd 0.548 V。 地址 0x4A(U6:CH13)/ 0x4B(U7:CH45),同样查表不要算。

本次新增/修改的文件

  • components/drv/include/ina226.h — 寄存器、量程常量、地址表、采样结构(唯一对外契约)
  • components/drv/ina226.c — 驱动本体(≈170 行,只经 hal_i2c_*)
  • components/drv/CMakeLists.txt — 新 IDF 组件 drv,REQUIRES phonerail_hal
  • test/test_ina226.c — 17 个用例
  • host/CMakeLists.txt — 加 PHONERAIL_DRV_SRCS 与 drv/include
  • main/CMakeLists.txt — REQUIRES phonerail_hal drv

验收命令与结果

$ bash host/test.sh
100% tests passed, 0 tests failed out of 4     # +test_ina226(17 个用例)

$ .\build_idf.ps1          # PowerShell
phonerail.bin binary size 0x32550 bytes. ... 0xcdab0 bytes (80%) free.
Project build complete.        # build/esp-idf/drv/.../ina226.c.obj 确认编到了

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

  • 别依赖 I²C 寄存器指针自增:sim 的假器件会自增,INA226 按 datasheet 不会。 「一次 write_read 连读 0x01~0x04」在宿主机上全绿,到板上四个量会读成同一个。 驱动每次读之前重写指针,test_pointer_is_rewritten_before_every_read 盯着这条。 (指针不自增这条未在实物上验过,B1 上板时确认。)
  • write_verify() 之后 last_write 是那次回读的指针字节(len 1),不是刚写的三字节。 按「最后一次写就是我写的数据」写断言会红一次 —— 改看 n_write/n_read 计数。
  • cygwin 并行链接偶发 Error running link command: Subprocess aborted(这次是 test_version)。 重跑一次就好,不是代码问题,别去查。

这个驱动的几条约定(写 A7 / A10 之前看一眼)

  • 地址查表:ina226_rail_addr(rail),rail 是 1~5(不是 0~4),越界 abort。 ina226_all_addr[6] 供扫描用;ina226_addr_table_ok() 做启动自检(含与 DAC 0x4A/0x4B、PCA9555 0x20、LM75 0x48 的撞车检查)。
  • 单位:bus_mv / shunt_uv / current_ua / power_mw,全是 int32_t。 电流 LSB 0.5 mA ⇒ current_ua 一定是 500 的整数倍;−60 mA(SW-8 判据)= -60000。
  • 巡检走 ina226_read_vi()(只读母线电压 + 电流,两次事务)—— §10.3 那 8 % 的 I²C 占用是按「每片每 20 ms 两次事务」算的,读四个量会翻倍。
  • HAL_ERR_BUS 在这个驱动里有特定含义:器件应答了但内容不对 (probe 的 ID 不匹配 = 贴错件/地址跳线焊错;init 的回读不一致;check 的 CAL 丢了)。 和「没这个器件」的 HAL_ERR_NAK 是两回事,降级矩阵(A15)要分开处理。
  • CAL 丢了不会报错,只会让 Current/Power 恒读 0,看上去像「这台手机不耗电」。 所以有 ina226_check(),巡检里定期查一次、不一致就 ina226_init() 重来并记事件。
  • Config 定为 0x4327(AVG=4、VBUSCT=VSHCT=1.1 ms、连续测量分流与母线), 转换周期 8.8 ms < t_safety 的 20 ms。改这个值前先算一遍这个不等式。