feat(main): 添加启动模块自检与汇总功能

- 新增 SystemBoot 类用于跟踪各模块初始化状态,提供位图标记与报告功能
- 在 main.cpp 中重构初始化流程,按顺序初始化各模块并记录状态
- 添加 system_boot.cpp 模块文件到构建配置
- CAN反馈任务增加冷启动延迟,避免与GD32初始化窗口冲突

refactor(ota): 优化OTA协调器线程安全机制

- 修改 lock()/unlock() 方法返回take结果,确保mutex正确释放
- 修复多任务并发时mutex死锁问题,避免vTaskPriorityDisinherit断言
- 统一finalize失败后的状态复位逻辑,确保协调器回到IDLE状态
- 优化忙状态超时检测与自愈机制

perf(boot): 优化冷启动时序与资源管理

- 简化README中冷启动优化说明,聚焦核心逻辑
- 优化BOD阈值设置为LVL5,改进电源稳定性
- 增加BLE OTA工作线程优先级,减少丢包情况
- 优化堆告警节流机制,在OTA期间降低告警频率

fix(relay): 改进GD32应用存活检测逻辑

- 调整GD32 APP存活验证时序,增加会话建立验证
- 修复HELLO建立session后未验证role的问题
- 优化FINISH后等待APP启动的静默时间与重试机制
- 统一GD32探测逻辑到OTA中继任务

refactor(server): 优化HTTP服务端内存与性能

- 使用静态缓冲区替代动态分配,减少堆碎片化风险
- 优化CAN批量发送期间暂停反馈任务的机制
- 调整BLE连接参数请求逻辑,提升传输性能
- 改进错误处理流程,避免堆紧张时的额外分配

bump(version): 更新固件版本至0.3.50

- 更新版本号从0.3.49到0.3.50
- 更新编译时间戳与Git哈希值
This commit is contained in:
小龙虾
2026-07-17 02:02:36 +08:00
parent 6364eacfb1
commit 1b10f89d8c
39 changed files with 851 additions and 331 deletions
+2 -4
View File
@@ -1,9 +1,7 @@
/*
* esp32_ota_core.cpp - ESP32 本机 OTA 核心流程实现(WiFi / BLE 通道共用)
* esp32_ota_core.cpp - ESP32 本机 OTA 核心流程(WiFi / BLE 通道共用)
*
* 设计依据 WiFi 原流程(wifi_ota.cpp 旧实现),修复已知 bug:
* - 旧 wifi_ota.cpp:625 在 esp_ota_end 成功后又调 esp_ota_abort → 用 m_ended 标志避免
* - SHA 统一从分区读回计算,不在传输过程中做增量 SHA
* SHA-256 在写入完成后从 OTA 分区读回计算;finalize 用 m_ended 区分 end 与 abort。
*/
#include <string.h>
#include <ctype.h>
+5 -19
View File
@@ -49,10 +49,7 @@ OtaCoordinator& OtaCoordinator::instance()
// ============================================================
bool OtaCoordinator::lock() const
{
// ★ 修复: 返回 take 结果,由调用方传回 unlock()。
// 旧实现用成员 bool m_locked 记录 take 结果,多任务并发 lock() 时
// 超时方会把 m_locked 置 false,覆盖持锁方的 true,导致 unlock() 跳过 give,
// mutex 永久死锁 → 后续 take 超时触发 vTaskPriorityDisinherit assert → PANIC。
/* 返回 take 是否成功;调用方须把该值传给 unlock() */
if (!m_mutex) return false;
bool ok = (xSemaphoreTake(m_mutex, kLockTimeout) == pdTRUE);
if (!ok) {
@@ -64,7 +61,7 @@ bool OtaCoordinator::lock() const
void OtaCoordinator::unlock(bool handle) const
{
// ★ 修复: 仅在对应的 lock() 成功 take 时才 give。
/* 仅当对应 lock() 成功时 give */
if (handle && m_mutex) {
xSemaphoreGive(m_mutex);
}
@@ -97,11 +94,7 @@ void OtaCoordinator::watchdogCheckLocked()
return; // 未超时
}
// ★ 超时自愈:完整中止到 IDLE(释放 Esp32OtaCore / 中继 / GD32 meta 等)。
// 旧逻辑只标 ERROR 不清理子系统:若卡在 FINALIZING 且 core 已半释放,
// 前端仍长时间判“占用”;若 core 仍持互斥,ERROR 后 begin 还要靠 forceCleanup。
// REBOOTING 本应已 esp_restart;超时则同样中止,避免永久卡死。
DEBUG_ERR(TAG, "忙状态 %d 卡死超过 %" PRIu32 " ms,强制中止 → IDLE",
DEBUG_ERR(TAG, "忙状态 %d 超过 %" PRIu32 " ms,强制中止 → IDLE",
(int)m_sysState, (uint32_t)pdTICKS_TO_MS(kBusyWatchdogTicks));
doAbortLocked();
}
@@ -580,9 +573,7 @@ Esp32FinalizeResult OtaCoordinator::finalizeForReboot(const char *frontend_sha_h
if (r.err == ESP_OK) {
notifyEsp32FinalizeComplete();
} else {
// ★ SHA 不匹配 / end 失败:Esp32OtaCore 已 abort+释放互斥,但协调器若仍停在
// ESP32_FINALIZING,WiFi 前端会一直被“设备 OTA 占用”拒绝(BLE 路径曾单独
// 补 abortCurrent;统一放到这里,WiFi/BLE 共用)。
/* finalize 失败:复位协调器到 IDLE */
DEBUG_ERR(TAG, "ESP32 finalize 失败: %s,复位协调器 → IDLE",
esp_err_to_name(r.err));
abortCurrent();
@@ -758,17 +749,12 @@ OtaSnapshot OtaCoordinator::getSnapshot() const
{
OtaSnapshot snap{};
// ── coordinator 自身状态(一次 mutex,避免二次加锁导致快照不一致)──
// 持锁时一次性取 m_sysState,并调不加锁的 stateToString()
// 就地转字符串。旧实现释放锁后再调 stateToString(getSystemState()) 二次加锁,
// 两次取值之间状态可能变化,导致 snap.sys_state 与 snap.sys_state_str
// 描述不同时刻状态。
/* 持锁一次读取状态并生成字符串,保证快照字段一致 */
bool h = lock();
if (h) {
snap.sys_state = m_sysState;
snap.channel = m_otaChannel;
snap.storage_done = m_gd32StorageDone;
// 就地把状态枚举转字符串,与 sys_state 来自同一时刻
snap.sys_state_str = stateToString(snap.sys_state);
unlock(h);
} else {
+3 -9
View File
@@ -469,20 +469,14 @@ private:
OtaCoordinator(const OtaCoordinator&) = delete;
OtaCoordinator& operator=(const OtaCoordinator&) = delete;
// 线程安全辅助
// ★ lock() 返回是否成功 take;unlock(handle) 据此决定是否 give。
// 旧实现用共享 bool m_locked 记录 take 结果,多任务并发 lock() 时
// 超时方会把 m_locked 置 false,覆盖持锁方的 true,导致 unlock() 跳过 give,
// mutex 永久死锁 → 后续 take 超时触发 vTaskPriorityDisinherit assert → PANIC。
// 线程安全:lock() 返回 take 是否成功;unlock(handle) 仅在成功时 give
bool lock() const;
void unlock(bool handle) const;
// ★ 卡死自愈检查:忙状态超时则 doAbortLocked → IDLE(不含 REBOOTING)。
// 必须在已持锁状态下调用。
// 忙状态超时检查(须已持锁);超时则 doAbortLocked → IDLE
void watchdogCheckLocked();
// ★ 已持锁版本的中止序列:根据当前 m_sysState 调用对应子模块的清理,
// 并把状态机复位为 IDLE。abortCurrent / abortCurrentIfEpoch 共享此实现。
// 已持锁中止:清理子系统并将状态复位为 IDLE
void doAbortLocked();
// ★ 已持锁版本的 ESP32 状态切换 helper:设置 m_sysState 并打印一条 INFO 日志。