/* TCA9548A —— 底板上的 I²C 八路多路器(U35,0x70),R2 新增(方案 D8)。 它的存在让五片刀片可以**完全同构**:每片上都是 0x40 的 INA226 + 0x20 的 PCA9555,零 strap 电阻、五片可互换。代价是**每一次访问刀片都先得选通道**。 ---- 这颗器件的三件反直觉的事 -------------------------------------------- 1. **它没有寄存器地址。** 整个器件只有一个 8 位控制寄存器,写就是「发一个 字节」、读就是「收一个字节」,**不带寄存器指针**。所以这里用的是 `hal_i2c_write(addr, &byte, 1)` 而不是常见的「写 reg + 写 val」。 按后者写会把通道选成 `reg` 那个字节的值 —— 而且**不会报错**。 2. **控制字是掩码不是编号。** bit n = 1 表示通道 n 接通,**可以同时开多路**。 同时开两路的后果是两片同地址的 INA226 一起应答,读回来的是两片的**线与** (量纲正常、数值偏小、还很稳)。所以本驱动只接受「恰好一路」或「全关」, 多路那种用法在这块板上永远是 bug。 3. **`RESET#` 只复位它自己**(把通道全关),不影响挂在支路上的器件。 复位脉冲很短(datasheet 最小 6 ns),但复位之后**通道是全关的** —— 所以调用方的通道影子必须一起作废,见 `i2cbus.h`。 ⚠️ 本驱动**不做加锁,也不管影子**。「选通道 + 事务」的原子性是 `i2cbus` 那一层的事(计划 §4.3)—— 混在这里会让驱动没法单独测。 */ #ifndef TCA9548A_H #define TCA9548A_H #include #include #include "hal_err.h" #ifdef __cplusplus extern "C" { #endif /* A0 = A1 = A2 = GND(U35 的 pin1 / pin2 / pin21,已按 PCB 焊盘网络核过)。 */ #define TCA9548A_ADDR 0x70 #define TCA9548A_CH_COUNT 8 /* 全关。`tca9548a_select()` 传这个值 = 断开所有支路,只剩主干可见 (主干上是 DAC63204 ×2 + 输入侧 INA226 + CH224A 以外的东西)。 */ #define TCA9548A_CH_NONE (-1) /* 通道 → 去哪(`.claude/r2/_base_pcb_nets.json` 的 `U35` 逐脚读回,2026-09-16)。 ⚠️ 槽 1~5 这次**确实是顺排的**,但通道号仍然从 `rail_cfg` 那张表里查 —— 顺排是当下的事实,不是不变量。 */ #define TCA9548A_CH_SLOT1 0 #define TCA9548A_CH_SLOT5 4 #define TCA9548A_CH_PD 5 /* SDA6/SCL6 → U36 CH224A(PD 受电芯片) */ /* 通道 6 / 7 悬空。 */ /* 0x70 不与 INA226(0x40/0x43) / DAC63204(0x4A/0x4B) / PCA9555(0x20) 撞车。 启动自检调一次。 */ bool tca9548a_addr_ok(void); /* 选通道。`ch` 是 0~7 或 `TCA9548A_CH_NONE`;其它值 → HAL_ERR_ARG。 **一次只开一路**(见文件头第 2 条)。 */ hal_err_t tca9548a_select(uint8_t addr, int ch); /* 读回控制字(一个字节,不带寄存器指针)。 用来验证「选通道真的生效了」—— 写下去不报错但没生效是这颗器件最难查的失效 (比如上拉太弱、支路被某个器件拉死)。 */ hal_err_t tca9548a_read_mask(uint8_t addr, uint8_t *mask); /* 认件:全关之后读回控制字,必须是 0。 不应答 → HAL_ERR_NAK;应答了但读回不是 0 → HAL_ERR_BUS(地址上有东西, 但它不是一颗听话的 TCA9548A)。 */ hal_err_t tca9548a_probe(uint8_t addr); /* 掩码 → 通道号。恰好一位才返回 0~7;全 0 返回 `TCA9548A_CH_NONE`; **多于一位返回 -2**(见文件头第 2 条:那是 bug,不是一种用法)。 */ int tca9548a_mask_to_ch(uint8_t mask); #ifdef __cplusplus } #endif #endif /* TCA9548A_H */