固件 0.1.5~0.1.13-c5:刷机模式、多组 WiFi、热插拔初始化、总线锁误判、硬重启断 VBUS
- 0.1.5/0.1.6:刷机模式(flash_mode,最多 2 路,60 分钟可加钟)——窗口内顶高按 4450 mV 绝对值判、不断 VBUS - 0.1.7/0.1.8:反灌断 VBUS 阈值放宽到 -300 mA(adb reboot bootloader 过渡实测 -208 mA) - 0.1.9:WiFi 最多存 4 组,连不上轮换;NVS v1 自动迁移并双写(OTA 回滚仍能上网) - 0.1.10:热插拔进来的刀片重新初始化 PCA9555 + INA226(否则 VBUS 常开、电流恒读 0) - 0.1.11:i2cbus 嵌套检测改看本任务持锁(原全局标志让 key 随机回 busy、vbus 随机回 io) - 0.1.12:硬重启先断 VBUS,开机校验通过 60 s 后再接回(否则假重启 / 误判没开机 / 进关机充电) - 0.1.13:这一路被安全判据断电时一并退出刷机模式(事件 21 arg 254) 26 ctest 全绿;新增用例均先在旧代码上确认变红。板 B 已 OTA 到 0.1.13-c5 并实测。 Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
这个提交包含在:
@@ -1231,6 +1231,113 @@ static void test_boot_check_first_press_boots(void)
|
||||
TEST_ASSERT_EQUAL_UINT32(0, sim_lock_violations(HAL_LOCK_I2C));
|
||||
}
|
||||
|
||||
/* ⭐ 0.1.11(板 B 实测):VBUS 通着做硬重启 —— 手机靠 USB 撑着没断电、直供电流 ≈ 0 ⇒
|
||||
校验判「没开起来」再按两下、断电时带着 USB 进关机充电。现在:断电前先断 VBUS,
|
||||
整个开机 + 校验期间都断着,开机校验通过才接回。 */
|
||||
static void test_hard_reset_cuts_vbus_first_and_restores_it_after_boot(void)
|
||||
{
|
||||
const int rail = 4;
|
||||
s_pg_val[rail - 1] = true;
|
||||
phone_up(1, false);
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, slot_vbus_enable(rail, true));
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail));
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN)); /* 断电之前就断了 */
|
||||
run_phone_ms(rail, HR_TO_PRESS_MS + ACT_HR_BOOT_KEY_MS + 10);
|
||||
TEST_ASSERT_EQUAL_INT(ACT_ST_HR_VERIFY, t_actuator_state(rail));
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN)); /* 校验期间也断着 */
|
||||
|
||||
for (int i = 0; i < 1000 && t_actuator_busy(rail); i++) {
|
||||
run_phone_ms(rail, 10); /* 走到校验刚结束的那一刻,从这里起算 60 s */
|
||||
}
|
||||
TEST_ASSERT_EQUAL_INT(ACT_RES_OK, t_actuator_last_result(rail));
|
||||
TEST_ASSERT_TRUE(s_boot_booted);
|
||||
/* 开起来了,但**还不接回**:这时手机在 bootloader / 内核早期,关充电补丁没生效,
|
||||
接回 USB 就被充到 4.4 V(板 B 实测 13 s 顶高断 VBUS)。执行器已空闲、不挡命令。 */
|
||||
TEST_ASSERT_FALSE(t_actuator_busy(rail));
|
||||
TEST_ASSERT_TRUE(t_actuator_vbus_back_pending(rail));
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
run_phone_ms(rail, ACT_HR_VBUS_BACK_MS - 1000);
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
run_phone_ms(rail, 1500);
|
||||
TEST_ASSERT_EQUAL_INT(1, pin(rail, PCA9555_BIT_VBUS_EN)); /* 到点:原样接回 */
|
||||
TEST_ASSERT_TRUE(slot_vbus_is_on(rail));
|
||||
TEST_ASSERT_FALSE(t_actuator_vbus_back_pending(rail));
|
||||
}
|
||||
|
||||
/* 等接回的这 60 s 里:有人手动动了 VBUS / 电,或者这一路被关了电 ⇒ 不再接回。 */
|
||||
static void test_a_pending_vbus_restore_is_dropped_when_someone_else_acts(void)
|
||||
{
|
||||
const int rail = 1;
|
||||
s_pg_val[rail - 1] = true;
|
||||
|
||||
/* ① 人手动断 VBUS(cmd 层会调 cancel)。 */
|
||||
phone_up(1, false);
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, slot_vbus_enable(rail, true));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail));
|
||||
run_phone_ms(rail, HR_TO_PRESS_MS + ONE_TRY_MS + 100);
|
||||
TEST_ASSERT_TRUE(t_actuator_vbus_back_pending(rail));
|
||||
t_actuator_cancel_vbus_back(rail);
|
||||
run_phone_ms(rail, ACT_HR_VBUS_BACK_MS + 1000);
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
|
||||
/* ② 这一路在等的时候被关了电(安全判据 / 拔刀片):到点也不接。 */
|
||||
phone_up(1, false);
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, slot_vbus_enable(rail, true));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail));
|
||||
run_phone_ms(rail, HR_TO_PRESS_MS + ONE_TRY_MS + 100);
|
||||
TEST_ASSERT_TRUE(t_actuator_vbus_back_pending(rail));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, rail_efuse_enable(rail, false));
|
||||
run_phone_ms(rail, ACT_HR_VBUS_BACK_MS + 1000);
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
TEST_ASSERT_FALSE(t_actuator_vbus_back_pending(rail));
|
||||
|
||||
/* ③ 再来一次硬重启:上一次排的接回作废(新的一次从头算)。 */
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, rail_efuse_enable(rail, true));
|
||||
phone_up(1, false);
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, slot_vbus_enable(rail, true));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail));
|
||||
run_phone_ms(rail, HR_TO_PRESS_MS + ONE_TRY_MS + 100);
|
||||
TEST_ASSERT_TRUE(t_actuator_vbus_back_pending(rail));
|
||||
phone_up(1, false);
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail)); /* VBUS 这时是断的 */
|
||||
TEST_ASSERT_FALSE(t_actuator_vbus_back_pending(rail));
|
||||
run_phone_ms(rail, HR_TO_PRESS_MS + ONE_TRY_MS + ACT_HR_VBUS_BACK_MS + 1000);
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
}
|
||||
|
||||
/* 没开起来 / 被打断:VBUS **不接回** —— 接回去就是让一台没开机的手机进关机充电。
|
||||
开始时本来就没通的,成功了也不许凭空打开。 */
|
||||
static void test_hard_reset_leaves_vbus_off_unless_the_phone_booted(void)
|
||||
{
|
||||
const int rail = 2;
|
||||
s_pg_val[rail - 1] = true;
|
||||
phone_up(0, false);
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, slot_vbus_enable(rail, true));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail));
|
||||
run_phone_ms(rail, HR_TO_PRESS_MS + 3 * ONE_TRY_MS + 1000);
|
||||
TEST_ASSERT_EQUAL_INT(ACT_RES_NO_BOOT, t_actuator_last_result(rail));
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
TEST_ASSERT_FALSE(slot_vbus_is_on(rail));
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, slot_vbus_enable(rail, true));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(rail));
|
||||
run_phone_ms(rail, ACT_HR_OFF_MS / 2);
|
||||
t_actuator_abort(rail);
|
||||
run_phone_ms(rail, ONE_TRY_MS);
|
||||
TEST_ASSERT_EQUAL_INT(ACT_RES_ABORTED, t_actuator_last_result(rail));
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(rail, PCA9555_BIT_VBUS_EN));
|
||||
|
||||
const int r5 = 5;
|
||||
s_pg_val[r5 - 1] = true;
|
||||
phone_up(1, false);
|
||||
TEST_ASSERT_FALSE(slot_vbus_is_on(r5));
|
||||
TEST_ASSERT_EQUAL_INT(HAL_OK, t_actuator_hard_reset(r5));
|
||||
run_phone_ms(r5, HR_TO_PRESS_MS + ONE_TRY_MS + 1000);
|
||||
TEST_ASSERT_EQUAL_INT(ACT_RES_OK, t_actuator_last_result(r5));
|
||||
TEST_ASSERT_EQUAL_INT(0, pin(r5, PCA9555_BIT_VBUS_EN));
|
||||
}
|
||||
|
||||
/* ⭐ 这次的主症状:第一下没压上,第二下开了。 */
|
||||
static void test_boot_check_presses_again_when_the_phone_stays_off(void)
|
||||
{
|
||||
@@ -1375,6 +1482,9 @@ int main(void)
|
||||
RUN_TEST(test_actuator_and_safety_share_one_lock_without_starving);
|
||||
|
||||
RUN_TEST(test_boot_check_first_press_boots);
|
||||
RUN_TEST(test_hard_reset_cuts_vbus_first_and_restores_it_after_boot);
|
||||
RUN_TEST(test_hard_reset_leaves_vbus_off_unless_the_phone_booted);
|
||||
RUN_TEST(test_a_pending_vbus_restore_is_dropped_when_someone_else_acts);
|
||||
RUN_TEST(test_boot_check_presses_again_when_the_phone_stays_off);
|
||||
RUN_TEST(test_boot_check_gives_up_after_three_presses_and_keeps_power);
|
||||
RUN_TEST(test_boot_check_does_not_press_again_when_current_is_unreadable);
|
||||
|
||||
在新工单中引用
屏蔽一个用户