A7:五路配置表 + 表驱动遍历 + 启动自检

六组编号(INA 地址 / DAC 片通道 / 三个按键位 / EDL 位 / 两根 EN 的 GPIO)拼成
一张 const 表 rail_cfg(1..5),没有一列是顺排的。开机 rail_selftest() 把它和
A3~A6 四个驱动的表逐格对账,再查全板引脚重复 / 越界,不过就 abort ——
那四个自检谓词至此全部有了调用点。

判据拎成 rail_selftest_table(t) 单独可调:真表是 const 的,不这么做就没法证明
「真有事的时候查得出来」。测试复制一张表出来逐样改坏,六种坏法都验过。

顺带修一个真 bug:HAL 两侧 GPIO 边界写的是 pin < 48,而 EFUSE_EN2 就在 IO48
上 —— CH2 的 eFuse 既开不了也关不掉。sim 与 ESP 两份都改成 0~48 含。

9 条 ctest(131 个用例)全绿,idf.py build 通过,16 条注错 15 条变红
(唯一没红的那条与原因记在 HANDOFF.md)。

Co-Authored-By: Claude Opus 5 <[email protected]>
这个提交包含在:
zhou yang
2026-09-07 07:13:04 +08:00
共同撰写人 Claude Opus 5
父节点 eb3df9ff49
当前提交 45de84ed3c
共修改 13 个文件,包含 1249 行新增和 63 行删除
@@ -9,9 +9,11 @@ typedef struct {
hal_gpio_mode_t mode;
int level;
uint32_t writes;
uint32_t seq; /* 最后一次被写时的全局序号,0 = 没写过 */
} pin_t;
static pin_t s_pin[SIM_GPIO_PINS];
static uint32_t s_seq; /* 全局写计数,从 1 开始发号 */
void sim_gpio_reset_internal(void); /* 只给 sim_hal_reset() 用 */
@@ -20,7 +22,11 @@ void sim_gpio_reset_internal(void); /* 只给 sim_hal_reset() 用 */
而 hal_gpio_write() 写同一个值也会计一次 writes。 */
void sim_sr595_gpio_hook(int pin, int level);
void sim_gpio_reset_internal(void) { memset(s_pin, 0, sizeof(s_pin)); }
void sim_gpio_reset_internal(void)
{
memset(s_pin, 0, sizeof(s_pin));
s_seq = 0;
}
static bool valid(int pin) { return pin >= 0 && pin < SIM_GPIO_PINS; }
@@ -51,6 +57,7 @@ hal_err_t hal_gpio_write(int pin, int level)
}
s_pin[pin].level = level ? 1 : 0;
s_pin[pin].writes++;
s_pin[pin].seq = ++s_seq;
sim_sr595_gpio_hook(pin, s_pin[pin].level);
return HAL_OK;
}
@@ -81,3 +88,5 @@ int sim_gpio_level(int pin)
}
uint32_t sim_gpio_writes(int pin) { return valid(pin) ? s_pin[pin].writes : 0; }
uint32_t sim_gpio_write_seq(int pin) { return valid(pin) ? s_pin[pin].seq : 0; }