文件
phonerail/firmware/components/drv/include/ch224a.h
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

76 行
3.9 KiB
C
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
/* CH224A —— 底板的 USB-PD 受电芯片(`U36`,R2 方案 D16)。
板上它只干一件事:用 `R7` 120 k 这一颗电阻**硬件**请求 20 V,
降压 `U37` 再把 20 V 变成 12 V 母线。固件**不参与协商**,只做一件事:
**读出当前这个充电器在 20 V 档最多能给多少电流**,换算成整板功率上限。
---- 为什么需要这个上限(计划 §5.9) ------------------------------------
R2 的输入从 DC 头改成了 USB-C PD。单口上限 20 V × 5 A = 100 W(5 A 还要
e-marker 线;普通 3 A 线只有 60 W),而整板最坏工况约 108 W。
常态 10~25 W 怎么都够,但**最坏工况要靠固件限功率**(R1 §8.3 的降载)。
充电器插的是哪一个,只有运行时才知道 —— 就是读这颗芯片。
┌─ ⛔ 一条禁令 ────────────────────────────────────────────────────────────┐
│ **本驱动不提供写 `0x0A` 的接口,一个都不提供。** │
│ `0x0A = 5` 是「请求 28 V EPR」。板上 `D3` 是 SMBJ22A(VRWM 22 V), │
│ `U37` 的 EN 分压按 20 V 设计 —— 28 V 会把 TVS 打到雪崩。 │
│ 这跟 `sr595.h` 不提供「抬 OE#」、`pca9555.h` 不提供「把接地脚配成输出」 │
│ 是同一条规矩:**能烧板子的动作不给接口,而不是给了再叮嘱别用。** │
└──────────────────────────────────────────────────────────────────────────┘
设计上挂在 TCA9548A 的**通道 5**(`TCA9548A_CH_PD`)上。
⚠️ **但 2026-09-27 板 B 实测它在主干应答**(0x22/0x23,mux 全关时也在),与设计不一致、原因未查。
`bringup.c` 的 `pd_up()` 两处都找(先主干);弄清之后删掉一处。 */
#ifndef CH224A_H
#define CH224A_H
#include <stdbool.h>
#include <stdint.h>
#include "hal_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ⚠️⚠️ **这个地址还没有被实物证实**(计划 §11 的待定项):
R2 §36.2 只写了寄存器号,没写从机地址。所以:
· 所有接口都**收一个 addr 参数**,不写死;
· B1 上板扫描时把通道 5 上扫到的那个地址填回这里,并同步改计划 §5.2。
在那之前,用这个值跑出来的「扫不到」是**预期结果**,不是固件 bug。 */
#define CH224A_ADDR_DEFAULT 0x23
/* 寄存器(R2 §36.2)。 */
#define CH224A_REG_STATUS 0x09 /* 协商状态 / 当前档位 */
#define CH224A_REG_CURRENT 0x50 /* 当前档位的最大电流,**单位 50 mA** */
/* 板上硬件固定请求的档位。`R7` 120 k 一颗电阻定死,固件改不了也不该改。 */
#define CH224A_FIXED_MV 20000
/* 0x50 那个字节 → mA。 */
uint32_t ch224a_ma_from_reg(uint8_t reg);
/* mA → 整板可用功率(mW),按 20 V 档算。
60 W / 65 W / 100 W 三档在这里分别是 3000 / 3250 / 5000 mA。 */
uint32_t ch224a_power_limit_mw(uint32_t ma);
/* 地址不与主干上的器件撞车。⚠️ 它挂在通道 5 上,与刀片支路的 0x40 / 0x20
本来就不冲突,这里查的是「万一它和主干某个器件同址」——
那种情况下选到通道 5 时主干那位会被它盖住。 */
bool ch224a_addr_ok(uint8_t addr);
/* 认件:读状态寄存器。不应答 → HAL_ERR_NAK。
⚠️ **不校验内容**:这颗芯片没有 ID 寄存器,状态字的每一个值都是合法的。 */
hal_err_t ch224a_probe(uint8_t addr);
hal_err_t ch224a_read_status(uint8_t addr, uint8_t *status);
/* 当前档位最大电流(mA)。读失败时 `*ma` 不动。 */
hal_err_t ch224a_read_max_ma(uint8_t addr, uint32_t *ma);
#ifdef __cplusplus
}
#endif
#endif /* CH224A_H */