固件 0.1.14~0.1.16-c5:Hub 按需启停(hubctl)、开机长按统一 5 s

Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
zhou yang
2026-10-04 19:24:31 +08:00
共同撰写人 Claude Opus 5.5
父节点 92f38c2328
当前提交 c41d1ec931
共修改 21 个文件,包含 764 行新增和 18 行删除
+45
查看文件
@@ -16,6 +16,7 @@
#include "hal_i2c.h"
#include "hal_lock.h"
#include "hal_time.h"
#include "hubctl.h"
#include "i2cbus.h"
#include "ina226.h"
#include "pca9555.h"
@@ -231,6 +232,7 @@ static void task_actuator(void *arg)
cmd_msg_t m;
for (;;) {
cmd_chgmode_tick(hal_time_now_ms()); /* 刷机模式到期清理 + 记事件(chgmode.h:只在本任务写) */
hubctl_tick(hal_time_now_ms()); /* Hub 按需启停(hubctl.h:只在本任务写)。空闲时 ≤100 ms 一拍 */
const TickType_t t = pdMS_TO_TICKS(t_actuator_step());
/* ⚠️ `CONFIG_FREERTOS_HZ=100` ⇒ 一个 tick 是 10 ms,`pdMS_TO_TICKS(5)`
是 **0**,而「等 0 tick」只是查一眼就回来 —— 那会让这个中优先级任务
@@ -342,6 +344,43 @@ static void want_save(void *ctx, int rail, bool on)
}
}
/* ---- Hub 模式的持久化(0.1.14,hubctl.h)-------------------------------------
同一个命名空间,一个字节。新板 / 读不到 = AUTO(用户 2026-09-29 定:默认按需)。 */
#define HUB_KEY "hub_mode"
static uint8_t hub_mode_load(void)
{
nvs_handle_t h;
uint8_t v = HUB_MODE_AUTO;
if (nvs_open(WANT_NS, NVS_READONLY, &h) == ESP_OK) {
if (nvs_get_u8(h, HUB_KEY, &v) != ESP_OK || v >= HUB_MODE_COUNT) {
v = HUB_MODE_AUTO;
}
nvs_close(h);
}
return v;
}
static void hub_mode_save(void *ctx, hub_mode_t mode)
{
(void)ctx;
if (hub_mode_load() == (uint8_t)mode) {
return; /* 没变就不写 flash */
}
nvs_handle_t h;
esp_err_t e = nvs_open(WANT_NS, NVS_READWRITE, &h);
if (e == ESP_OK) {
e = nvs_set_u8(h, HUB_KEY, (uint8_t)mode);
if (e == ESP_OK) {
e = nvs_commit(h);
}
nvs_close(h);
}
if (e != ESP_OK) {
ESP_LOGW(TAG, "Hub 模式没存进 NVS:%s(这次照样生效)", esp_err_to_name(e));
}
}
static void log_report(const bringup_report_t *r)
{
ESP_LOGI(TAG, "启动:降级位 0x%02x,空槽 0x%02x,盲跑 0x%02x,PCA 失联 0x%02x,PD %u mA → 上限 %u mW",
@@ -441,6 +480,12 @@ void app_main(void)
ESP_LOGE(TAG, "风扇起不来:%s —— 没有主动散热", hal_err_str(err));
}
/* Hub 按需启停(0.1.14)。放开 `HUB_RST#`、启动算一次「需要」⇒ 至少 HUB_IDLE_MS 之后才可能关。
必须在执行器任务起来之前:它的第一拍就会调 `hubctl_tick()`。 */
hubctl_init((hub_mode_t)hub_mode_load(), hub_mode_save, NULL, hal_time_now_ms());
ESP_LOGI(TAG, "Hub 模式 %s(无人用 USB %u 分钟后按住复位)", hub_mode_str(hubctl_mode()),
(unsigned)(HUB_IDLE_MS / 60000u));
/* 执行器:PG 从巡检的快照里取,本任务自己不碰 I²C(t_actuator.h 开头那一段)。
⚠️ 必须在 `spawn(TASK_SAFETY, ...)` 之前:判据要关路时会先 `t_actuator_abort()`,
而没 init 的执行器只会直接返回,那时序列还在跑,电关掉几秒又会被抬回来。 */