固件 0.1.4-c5:整片刀片不应答(INA226 + PCA9555 同时 NAK 200 ms)⇒ 关这一路
- t_safety:eFuse 开着、本路两颗都 NAK 连续 10 圈 ⇒ abort + 关 eFuse,新事件 20 BLADE_MUTE; 只关 eFuse,不再写刚 NAK 过的 PCA9555。只有一颗不答应仍按 §10.10 盲跑、保持供电 - 起因:板 B 第 2 槽 PRSNT2# 卡低,刀片挪走后空槽 eFuse 开了约 4 h,原判据一条没响 - 需求 §10.10 加一行 + 表后第 3 条;rack 事件 20 命名并标红 - 宿主机 26 ctest 全绿(test_t_safety_rules +4 例) Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -217,6 +217,7 @@ log_ev_t evlog_from_safety(uint8_t safety_ev)
|
||||
case SAFETY_EV_PUSHED_UP: return LOG_EV_PUSHED_UP;
|
||||
case SAFETY_EV_MUX_LOST: return LOG_EV_MUX_LOST;
|
||||
case SAFETY_EV_SLOT_EMPTY: return LOG_EV_SLOT_EMPTY;
|
||||
case SAFETY_EV_BLADE_MUTE: return LOG_EV_BLADE_MUTE;
|
||||
case SAFETY_EV_NONE: break;
|
||||
}
|
||||
return LOG_EV_NONE;
|
||||
@@ -574,6 +575,7 @@ const char *evlog_ev_str(log_ev_t ev)
|
||||
case LOG_EV_PG_TIMEOUT: return "上电等不到PG";
|
||||
case LOG_EV_OTA: return "固件升级";
|
||||
case LOG_EV_BOOT_CHECK: return "开机重按";
|
||||
case LOG_EV_BLADE_MUTE: return "刀片不应答关路";
|
||||
case LOG_EV_COUNT: break;
|
||||
}
|
||||
return "?";
|
||||
|
||||
@@ -88,6 +88,11 @@ typedef enum {
|
||||
频繁出现 = 这一台的电源键弹片和刀片铜盘接触不良(2026-09-28 板 B 第 1 路)。 */
|
||||
LOG_EV_BOOT_CHECK = 19,
|
||||
|
||||
/* 0.1.4 新增:整片刀片不应答(本路 INA226 + PCA9555 连续 10 圈都 NAK,eFuse 开着)⇒ 关这一路。
|
||||
`t_safety.h` 的 `T_SAFETY_BLADE_MUTE_N`。bus_mv / current_ua 是上一次读到的旧值,仅供参考。
|
||||
出现 = 这一槽 `PRSNT#` 假在位,或刀片的 I²C 整个断了。 */
|
||||
LOG_EV_BLADE_MUTE = 20,
|
||||
|
||||
LOG_EV_COUNT,
|
||||
} log_ev_t;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define PHONERAIL_H
|
||||
|
||||
/* 固件版本。规则:<主>.<次>.<修订>-<最后完成的任务包> */
|
||||
#define PHONERAIL_FW_VERSION "0.1.3-c5"
|
||||
#define PHONERAIL_FW_VERSION "0.1.4-c5"
|
||||
|
||||
/* 通道数。五路直供,见设计文档 §2。 */
|
||||
#define PHONERAIL_RAIL_COUNT 5
|
||||
|
||||
+23
-1
@@ -43,6 +43,8 @@ const char *t_safety_ev_str(safety_ev_t ev)
|
||||
return "mux失联全断";
|
||||
case SAFETY_EV_SLOT_EMPTY:
|
||||
return "刀片不在位";
|
||||
case SAFETY_EV_BLADE_MUTE:
|
||||
return "刀片不应答关路";
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
@@ -183,7 +185,27 @@ static hal_err_t cycle_rail(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* 判据就在这里跑:断 VBUS 要在本路通道选好、锁还持着的此刻(规矩 3)。 */
|
||||
/* 整片刀片不应答(T_SAFETY_BLADE_MUTE_N 的理由)。**不走 `trip_rail_locked()`**:
|
||||
它要先写这片 PCA9555 断 VBUS,而这片刚刚 NAK 过 —— 再发一次只是白等十几 ms 的
|
||||
IDF NAK 超时、把本圈预算吃光(规矩 4)。只关 eFuse(锁外,GPIO 直连,永远关得掉)。
|
||||
判据本身不发任何事务:两个 ok 位是上面刚读出来的。 */
|
||||
safety_rail_t *st = &s->st[rail - 1];
|
||||
if (rail_efuse_is_on(rail) && !s->rail_ok[rail - 1] && !s->io_ok[rail - 1]) {
|
||||
if (st->mute_n < 0xFF) {
|
||||
st->mute_n++;
|
||||
}
|
||||
if (st->mute_n >= T_SAFETY_BLADE_MUTE_N) {
|
||||
st->pend_abort = true;
|
||||
st->pend_efuse = true;
|
||||
st->pend_ev = (uint8_t)SAFETY_EV_BLADE_MUTE;
|
||||
/* 同 SR-5:不清零。关掉之后下一圈 en 为 false 自然清;写引脚失败的话下一圈立刻再关。 */
|
||||
}
|
||||
} else {
|
||||
st->mute_n = 0;
|
||||
}
|
||||
|
||||
/* 判据就在这里跑:断 VBUS 要在本路通道选好、锁还持着的此刻(规矩 3)。
|
||||
rail_ok 为 false 时它第一道闸就返回,不会盖掉上面攒下的 BLADE_MUTE。 */
|
||||
judge_locked(s, rail, a->now);
|
||||
return first;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,16 @@ extern "C" {
|
||||
在拿旧数据跑判据。判定成立之后**先脉冲一次 `MUX_RST#`**,再不行才全断。 */
|
||||
#define T_SAFETY_MUX_FAIL_N 3
|
||||
|
||||
/* ⭐ 0.1.4:**整片刀片不应答**(本路 INA226 与 PCA9555 **同时** NAK)连续多少圈就关这一路。
|
||||
与 §10.10 第一行「INA226 无应答 → 盲跑、保持供电」不冲突:那一行是**一颗**器件坏了,
|
||||
刀片上的另一颗还答应;两颗都不答应而 mux 是好的(选不中的话本路读函数根本不会被调,
|
||||
计不进来),只剩两种可能 ——
|
||||
· 刀片根本不在,是 `PRSNT#` 假在位(2026-09-28 板 B 第 2 槽:卡低之后空槽 eFuse 开了约 4 h);
|
||||
· 刀片在,但这一路完全失控:看不到 V/I、看不到 PG/FLT、**连 VBUS 都断不了**。
|
||||
两种都是「继续供电但看不见」,和 mux 失联全断同一个道理,只是范围是一路。
|
||||
10 圈 = 200 ms:本板实测单路 9 万圈 0 次 NAK,连续 10 次不是毛刺;空槽带 12 V 多 200 ms 无所谓。 */
|
||||
#define T_SAFETY_BLADE_MUTE_N 10
|
||||
|
||||
/* ---- A10:事件(§10.7 的「单条」形状) -----------------------------------
|
||||
A11 把这条记录塞进环形缓冲,这里只负责**产生**它。 */
|
||||
|
||||
@@ -130,6 +140,8 @@ typedef enum {
|
||||
/* ⭐ R2 新增两条(计划 §5.8)。放在**末尾**:`evlog` 那边的数字是 flash 格式。 */
|
||||
SAFETY_EV_MUX_LOST, /* TCA9548A 连续选不中 ⇒ 五路全部断电(单点) */
|
||||
SAFETY_EV_SLOT_EMPTY, /* `PRSNT#` 为高(刀片不在位)⇒ 这一路不许带电 */
|
||||
/* 0.1.4,同样只许加在末尾。 */
|
||||
SAFETY_EV_BLADE_MUTE, /* 本路 INA226 + PCA9555 连续 T_SAFETY_BLADE_MUTE_N 圈都不应答 ⇒ 关这一路 */
|
||||
} safety_ev_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -153,6 +165,7 @@ typedef struct {
|
||||
bool en_on; /* 上一圈看到的 `EFUSE_EN` 影子,用来认它的上升沿 */
|
||||
uint32_t en_ms; /* 上升沿的时刻,缓启动窗口从这里算(这个是真按毫秒的) */
|
||||
uint8_t dev_n; /* 连着几圈越界了。回到范围内 / 这一路被关掉就清零 */
|
||||
uint8_t mute_n; /* 开着电、整片刀片连着几圈不应答。任一颗答应了 / 这一路关着就清零 */
|
||||
|
||||
/* 本圈锁内判据留给锁外的两件事(规矩 3:VBUS 锁内断,eFuse 锁外关)。 */
|
||||
uint8_t pend_ev; /* safety_ev_t,0 = 没有 */
|
||||
|
||||
在新工单中引用
屏蔽一个用户