固件 0.1.17~0.1.18-c5:CH224A 的 PD 档位实时进遥测(pdmon)
原来只在启动时读一次(bringup.c),而多口充电器重新分配功率时 20 V 档的电流上限当场会变。
- 新模块 pdmon:每秒读 0x09(协议状态)+ 0x50(档位电流),只读;先试上次应答的支路(主干 / mux 通道 5)。
档位变了(连续两拍一致、非 0)记 LOG_EV_PD_LIMIT,arg 2 = 运行中换档。只报不动,降载仍没人做。
- status 新增 "pd":{"st":..,"ma":..},这一拍没读到是 null(满配 1164 / 1536 字节,余量断言改成至少留 256)。
- 0.1.17 放在热管理任务里读,板 B 实测 safety.skipped 每秒涨 1(持锁撞上巡检的下一拍);
0.1.18 挪进巡检任务(t_safety_step 之后、每 50 圈一次),skipped 不再涨。
- 测试:新增 test_pdmon(6 例),test_cmd 加 pd 断言;28 ctest 全绿。
板 B 已 OTA 到 0.1.18-c5(两次都是热重启,五路没断电),读到 st 0x88 / 3000 mA。
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -0,0 +1,72 @@
|
||||
/* CH224A 运行期轮询。契约见 pdmon.h。 */
|
||||
#include "pdmon.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户