固件 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]>
这个提交包含在:
zhou yang
2026-09-29 08:16:21 +08:00
共同撰写人 Claude Opus 5.5
父节点 385d2f9c47
当前提交 9fb5bba367
共修改 35 个文件,包含 5120 行新增和 3675 行删除
+57 -7
查看文件
@@ -18,9 +18,20 @@ void netcfg_init(const netcfg_t *loaded, netcfg_save_fn save, netcfg_changed_fn
if (loaded != NULL) {
s_cfg = *loaded;
}
/* 从 flash 读回来的东西不可信:强制收尾,免得一个没带 0 的字段把后面的读穿。 */
s_cfg.ssid[NETCFG_SSID_MAX] = '\0';
s_cfg.pass[NETCFG_PASS_MAX] = '\0';
/* 从 flash 读回来的东西不可信:强制收尾,免得一个没带 0 的字段把后面的读穿;
空位挤到末尾(「有效的就是 [0, n)」是 count / 轮换的前提)。 */
int n = 0;
for (int i = 0; i < NETCFG_WIFI_N; i++) {
netcfg_wifi_t w = s_cfg.wifi[i];
w.ssid[NETCFG_SSID_MAX] = '\0';
w.pass[NETCFG_PASS_MAX] = '\0';
if (w.ssid[0] != '\0') {
s_cfg.wifi[n++] = w;
}
}
for (int i = n; i < NETCFG_WIFI_N; i++) {
memset(&s_cfg.wifi[i], 0, sizeof(s_cfg.wifi[i]));
}
s_cfg.uri[NETCFG_URI_MAX] = '\0';
s_cfg.user[NETCFG_USER_MAX] = '\0';
s_cfg.mpass[NETCFG_MPASS_MAX] = '\0';
@@ -90,6 +101,25 @@ static hal_err_t commit(const netcfg_t *next)
return HAL_OK;
}
int netcfg_wifi_count(const netcfg_t *cfg)
{
int n = 0;
while (n < NETCFG_WIFI_N && cfg->wifi[n].ssid[0] != '\0') {
n++;
}
return n;
}
int netcfg_wifi_find(const netcfg_t *cfg, const char *ssid)
{
for (int i = 0; i < netcfg_wifi_count(cfg); i++) {
if (strcmp(cfg->wifi[i].ssid, ssid) == 0) {
return i;
}
}
return -1;
}
hal_err_t netcfg_set_wifi(const char *ssid, const char *pass)
{
if (!netcfg_wifi_ok(ssid, pass)) {
@@ -97,10 +127,30 @@ hal_err_t netcfg_set_wifi(const char *ssid, const char *pass)
}
netcfg_t next;
netcfg_get(&next);
memset(next.ssid, 0, sizeof(next.ssid));
memset(next.pass, 0, sizeof(next.pass));
strcpy(next.ssid, ssid);
strcpy(next.pass, pass);
int i = netcfg_wifi_find(&next, ssid);
if (i < 0) {
i = netcfg_wifi_count(&next);
if (i >= NETCFG_WIFI_N) {
return HAL_ERR_STATE; /* 满了:先删一组。不悄悄挤掉最老的 —— 那可能正是唯一连得上的 */
}
}
memset(&next.wifi[i], 0, sizeof(next.wifi[i]));
strcpy(next.wifi[i].ssid, ssid);
strcpy(next.wifi[i].pass, pass);
return commit(&next);
}
hal_err_t netcfg_del_wifi(const char *ssid)
{
netcfg_t next;
netcfg_get(&next);
const int i = ssid != NULL ? netcfg_wifi_find(&next, ssid) : -1;
if (i < 0) {
return HAL_ERR_ARG;
}
const int n = netcfg_wifi_count(&next);
memmove(&next.wifi[i], &next.wifi[i + 1], (size_t)(n - 1 - i) * sizeof(next.wifi[0]));
memset(&next.wifi[n - 1], 0, sizeof(next.wifi[0]));
return commit(&next);
}