feat(esp32): 添加多电机OTA中继功能并优化调试日志系统

- 新增多电机状态、版本和OTA中继监控模块(monitor/motor_state.cpp,
  monitor/motor_version.cpp, monitor/motor_ota_relay.cpp)
- 在CAN反馈任务中添加0xC5/0xC6/0xD2类型消息处理,支持多电机状态推送
- 重构调试日志系统,将一次性JSON分配改为512B栈缓冲流式发送,降低内存峰值
- 调试UART波特率从115200提升至30000
- 修改版本管理方式,从自动生version.h改为手动维护
- 更新VSCode设置以支持ESP-IDF开发环境配置
- 在OTA协调器中添加电机OTA互斥机制,防止并发冲突
- 完善中继状态机异常处理,添加远程取消通知机制
This commit is contained in:
小龙虾
2026-07-26 20:40:16 +08:00
parent 770ae14156
commit 2138a572ee
47 changed files with 6469 additions and 799 deletions
+29 -1
View File
@@ -75,9 +75,37 @@ const esp_partition_t* Gd32FlashStore::getPartition()
// Flash 分区读写
// ============================================================
void Gd32FlashStore::beginWriteSession()
void Gd32FlashStore::beginWriteSession(bool full_erase)
{
m_erasedUpTo = 0;
if (!full_erase) {
return; // GD32 OTA:保持原优化,由 flashWriteChunk 按需擦除与收流交织
}
/* ★ motor OTA:强制擦除整个 gd32_ota 分区,而不是只重置水位。
* 之前只重置 m_erasedUpTo=0,依赖 flashWriteChunk 按需擦除覆盖到的扇区,
* 导致两类隐患:
* 1. 上次刷的更大固件在高位扇区残留,本次若擦除位错误会与残留 AND 产生位翻转
* (正是 0xAC20 处 0x19→0x18 单 bit 翻转的根因)。
* 2. ensureErasedForWrite 按水位推进,若某次擦除返回 OK 但物理失败,
* 旧数据残留 + AND 语义写入 = 静默位错误。
* 强制全擦(252KB ~200ms)确保每次上传从全 0xFF 干净状态开始,
* 即使新固件只覆盖前 44KB,剩余高位扇区也回到擦除态,杜绝残留干扰。
* 擦除失败立刻报错,不让坏状态继续。 */
const esp_partition_t *part = getPartition();
if (!part) {
DEBUG_ERR("OTA", "beginWriteSession: 分区未找到,无法预擦除");
return;
}
esp_err_t err = erasePartition(part->size);
if (err != ESP_OK) {
DEBUG_ERR("OTA", "beginWriteSession: 预擦除整个分区失败: %s", esp_err_to_name(err));
/* 不 return(void 函数);后续 flashWriteChunk 的 ensureErasedForWrite
* 仍会尝试擦除目标扇区,给数据写入多一次机会。 */
} else {
m_erasedUpTo = part->size; /* 全擦完成,后续 ensureErasedForWrite 全部跳过 */
DEBUG_INFO("OTA", "beginWriteSession: 已预擦除整个 gd32_ota 分区 (%lu B)",
(unsigned long)part->size);
}
}
/** @brief 确保 [offset, offset+len) 覆盖的扇区已擦除(从 m_erasedUpTo 顺序推进)。 */
+3 -2
View File
@@ -72,9 +72,10 @@ public:
/**
* @brief 新一轮 GD32 固件写入会话开始时调用:复位擦除水位。
* 后续 flashWriteChunk 经 ensureErasedForWrite 按需擦扇区。
* @param full_erase true=强制擦除整个分区(motor OTA 用,杜绝旧固件残留导致的位错误);
* false=只重置水位,由 flashWriteChunk 按需擦扇区(GD32 OTA 用,与收流交织)。
*/
void beginWriteSession();
void beginWriteSession(bool full_erase = false);
// ── NVS 元数据持久化 ──