/* CH224A 运行期轮询。契约见 pdmon.h。 */ #include "pdmon.h" #include #include "ch224a.h" #include "evlog.h" #include "i2cbus.h" #include "slot.h" #include "tca9548a.h" typedef struct { uint8_t status; uint32_t ma; } pd_read_t; static pdmon_snap_t s_snap; static int s_ch = I2CBUS_CH_TRUNK; /* 上次应答的支路 */ static uint32_t s_logged_ma; /* 最近一次进了日志的档位 */ static uint32_t s_prev_ma; /* 上一拍读到的(去抖用) */ static hal_err_t read_fn(void *arg) { pd_read_t *r = (pd_read_t *)arg; const hal_err_t err = ch224a_read_status(CH224A_ADDR_DEFAULT, &r->status); return (err == HAL_OK) ? ch224a_read_max_ma(CH224A_ADDR_DEFAULT, &r->ma) : err; } void pdmon_init(uint32_t boot_ma) { s_snap = (pdmon_snap_t){ 0 }; s_ch = I2CBUS_CH_TRUNK; s_logged_ma = boot_ma; s_prev_ma = boot_ma; } void pdmon_poll(void) { pd_read_t r = { 0 }; hal_err_t err = i2cbus_xact(s_ch, SLOT_LOCK_TIMEOUT_MS, read_fn, &r); if (err != HAL_OK) { const int other = (s_ch == I2CBUS_CH_TRUNK) ? TCA9548A_CH_PD : I2CBUS_CH_TRUNK; err = i2cbus_xact(other, SLOT_LOCK_TIMEOUT_MS, read_fn, &r); if (err == HAL_OK) { s_ch = other; } } s_snap.polls++; if (err != HAL_OK) { s_snap.ok = false; /* 值留着:旧的档位比一个 0 可信(ch224a.h 同一条) */ s_snap.errors++; return; } s_snap.status = r.status; s_snap.ma = r.ma; s_snap.ok = true; /* 换档:连续两拍读到同一个非零值、且和日志里最后那条不一样。0 = 协商中途 / 没协商上,不记。 */ if (r.ma != 0 && r.ma == s_prev_ma && r.ma != s_logged_ma) { s_logged_ma = r.ma; evlog_put(0, LOG_EV_PD_LIMIT, PDMON_EV_ARG_CHANGED, (int32_t)(ch224a_power_limit_mw(r.ma) / 100u), (int32_t)r.ma); } s_prev_ma = r.ma; } void pdmon_get(pdmon_snap_t *out) { if (out != NULL) { *out = s_snap; } }