A6:PCA9555 驱动 + 「接地脚永远是输入」的硬约束
U23 @ 0x20,16 个脚全部是输入:5×EFUSE_FLT# + 5×EFUSE_PGOOD + BUCK_PG + INA_ALERT + 4 个焊死在地上的备用脚(P0_7 / P1_5~7)。位表与地址从 .claude/pcb1-parts.json 的真实焊盘网络逐脚核回来,与设计文档 §17.2 一致。 驱动根本不提供「把某个脚配成输出」的接口(和 sr595.h 不提供「抬 OE#」同一条 规矩),方向字一律过 pca9555_dir_safe(),不安全直接 abort。原因是 PCA9555 的 Output Port 寄存器复位值是 0xFF —— 把接地脚配成输出的那一刻它就输出高电平, 而真器件既不报错也不 NAK,只是发烫。 三种极性(FLT# 低有效 / PGOOD 高有效 / INA_ALERT 低有效)各自只在一个函数里 出现一次;上层问「有没有故障」,不许自己去 & 位。 sim 侧新增按 datasheet 建模的假 PCA9555:Output 复位 0xFF、输入按位合成、 接地脚被驱动时记短路、INT# 只被「读输入端口」清除。为此给假 I²C 总线加了一个 窃听钩子(POST_WRITE / PRE_READ)—— 通用寄存器表模拟不了「配成输出就对地 短路」这类事,以后再有这种器件照这个挂。 验收:8 条 ctest(81 用例)全绿;idf.py build 通过,pca9555.c.obj 在。 12 个「一定会被写出来的错」逐个注进去跑过,全部变红。 Co-Authored-By: Claude Opus 5 <[email protected]>
这个提交包含在:
@@ -413,6 +413,26 @@ typedef struct {
|
||||
同理,**PCA9555 的方向寄存器只能配成全输入**:备用脚 Port0[7] / Port1[7:5] 在硬件上
|
||||
直接接地,配成输出并写 1 就是对地短路(设计文档 §17.2 已在图纸上注明)。
|
||||
|
||||
> **A6 已落地**:驱动在 `firmware/components/drv/include/pca9555.h`,
|
||||
> **根本不提供「把某个脚配成输出」的接口**(和 sr595.h 不提供「抬 OE#」同一条规矩)。
|
||||
> 方向字一律过 `pca9555_dir_safe()`,不安全直接 abort。
|
||||
> 同处还记了四条这一片的实现约定:
|
||||
> ① ⚠️ **Output Port 寄存器的复位值是 0xFF** —— 所以把接地脚配成输出的那一刻它就
|
||||
> 输出高电平,中间没有「先写个 0 再说」的余地,这比「配错方向」本身更急;
|
||||
> ② **极性反转寄存器必须无条件清零**,不能赌复位值:看门狗只复位 ESP32,
|
||||
> PCA9555 不掉电,上一条命的残留值原样留着,而写错的现象是「五路同时报故障」
|
||||
> 或者更糟的「五路故障全都看不见」,I²C 一切正常;
|
||||
> ③ **三种极性**(FLT# 低有效 / PGOOD 高有效 / INA_ALERT 低有效)各自只在
|
||||
> `pca9555_rail_fault()` 等四个函数里出现一次,上层不许自己去 & 位;
|
||||
> ④ **INT# 是加速路径不是主路径**:它要读走输入端口才释放,漏读一次就再也等不到
|
||||
> 下一个沿,所以 `t_safety` 必须无条件轮询(§10.3 的 20 ms 就是按这个排的)。
|
||||
>
|
||||
> ⚠️ **FLT 与 PG 两张位表这次确实是顺排的**(都是 `bit = rail - 1`),
|
||||
> 和 INA226 地址、595 位号那两张表不一样。所以这里最容易写出来的错不是「算式」,
|
||||
> 而是**把 Port0 和 Port1 搞反** —— 两个端口的 bit0~4 长得一模一样,搞反之后
|
||||
> 「有故障」会被读成「电源良好」,方向正好相反,而且**静息态两个端口读回来都是
|
||||
> 全 1,单看一帧完全看不出来**。`test_one_rail_at_a_time` 专门拦这一手。
|
||||
|
||||
### 10.5 电压通道:DAC 只做微调,而且是反向的
|
||||
|
||||
| 事实 | 含义 |
|
||||
|
||||
在新工单中引用
屏蔽一个用户