feat(ota): 实现GD32 OTA包间背压机制,优化传输节奏控制
移除固定的包间延迟配置 `OTA_PACKET_DELAY_MS`,采用基于SPI Link v2 CREDIT背压的动态节奏控制,在SpiMaster中通过remoteCredit==0时wait/拒发 实现流量控制,提高OTA传输稳定性。 refactor(stack): 统一任务栈大小配置并添加CPU统计功能 - 在app_config.h中集中定义所有任务栈大小常量,基于实测水位优化分配 - 新增monitor/cpu_stats.cpp组件,提供1Hz FreeRTOS CPU占用采样 - 更新main.cpp中的任务创建使用新的栈大小常量 - 调整health_monitor和ota_relay等任务的栈分配 perf(ota): 改进ESP32和GD32 OTA分区预擦策略 - ESP32 OTA从边写边擦改为整分区预擦模式,避免写入时的扇区擦除阻塞 - GD32 OTA在prepare阶段进行整分区预擦,提升后续写入吞吐量 - 优化OTA协调器状态管理,修复FINALIZING状态残留问题 fix(log): 改进UDP日志发送的堆内存管理 - 当堆内存不足时记录UDP发送跳过的告警信息到ring buffer - 降低UDP发送跳过的内存阈值从10KB到6KB - 降低日志排水最小内存阈值从8KB到4KB docs(readme): 更新OTA配置参数文档说明 移除已废弃的OTA_PACKET_DELAY_MS参数,更新包间节奏控制说明为 基于CREDIT背压机制的描述。
This commit is contained in:
@@ -136,7 +136,7 @@ esp_err_t Gd32FlashStore::flashWriteChunk(uint32_t offset, const uint8_t *data,
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
// 写入前按需擦除目标扇区(替代 prepare 阶段整段预擦)
|
||||
// 正常路径:prepare 已整分区预擦;此处仅兜底(水位未覆盖时才擦)
|
||||
esp_err_t erase_err = ensureErasedForWrite(aligned_offset, aligned_len);
|
||||
if (erase_err != ESP_OK) {
|
||||
return erase_err;
|
||||
@@ -457,7 +457,7 @@ esp_err_t Gd32FlashStore::metaVerifyChecksum()
|
||||
|
||||
// 检查 checksum 是否全零(未计算过)
|
||||
// 注意:返回 INVALID_STATE 而非 ESP_OK,由调用方决定是否容忍。
|
||||
// 历史上这里直接返回 OK 跳过校验,但 meta 被意外清零时会掩盖固件损坏。
|
||||
// 若直接返回 OK 跳过校验,meta 被意外清零时会掩盖固件损坏。
|
||||
static const uint8_t kZeroSha[32] = {0};
|
||||
if (memcmp(meta.checksum, kZeroSha, sizeof(meta.checksum)) == 0) {
|
||||
DEBUG_WARN("OTA", "metaVerify: checksum 未计算,返回 INVALID_STATE(调用方决定容忍或失败)");
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
/*
|
||||
* gd32_flash_store.h - GD32 OTA 固件 Flash 存储抽象层
|
||||
*
|
||||
* 从 OtaRelay 中剥离的 Flash 分区读写、NVS 元数据持久化和 SHA-256 校验职责。
|
||||
* 传输层(WiFi/BLE)和 OtaRelay 均通过本类操作 GD32 固件存储,
|
||||
* 不再由 OtaRelay 承担存储职责(解决 H1 职责超载)。
|
||||
* 封装 Flash 分区读写、NVS 元数据持久化和 SHA-256 校验。
|
||||
* 传输层(WiFi/BLE)和 OtaRelay 均通过本类操作 GD32 固件存储。
|
||||
*
|
||||
* 线程模型:
|
||||
* - 通过 instance() 单例访问,NVS 元数据读写由内部 mutex 保护
|
||||
@@ -72,8 +71,8 @@ public:
|
||||
esp_err_t erasePartition(uint32_t size);
|
||||
|
||||
/**
|
||||
* @brief 新一轮 GD32 固件写入会话开始时调用:复位按需擦除水位。
|
||||
* prepareGd32Storage 在开始收流前调用,避免整段预擦阻塞 HTTP/BLE 收包。
|
||||
* @brief 新一轮 GD32 固件写入会话开始时调用:复位擦除水位。
|
||||
* prepareGd32Storage 随后会 erasePartition(整分区)。
|
||||
*/
|
||||
void beginWriteSession();
|
||||
|
||||
@@ -153,9 +152,8 @@ private:
|
||||
|
||||
const esp_partition_t *m_partition = nullptr; ///< gd32_ota 分区指针(懒初始化)
|
||||
|
||||
// ── 按需擦除水位:已保证 [0, m_erasedUpTo) 为擦除态(扇区对齐)──
|
||||
// 收流时 flashWriteChunk 按写入范围推进擦除,替代上传前整段预擦。
|
||||
// 这样 HTTP 主线程可边收边擦写,浏览器进度不会在“100% 发完”后空等整段擦除。
|
||||
// ── 擦除水位:prepare 整分区预擦后 m_erasedUpTo==part->size;
|
||||
// flashWriteChunk 内 ensureErased 为安全兜底(水位已覆盖则立即返回)。
|
||||
static constexpr uint32_t kFlashSectorSize = 4096U;
|
||||
uint32_t m_erasedUpTo = 0;
|
||||
esp_err_t ensureErasedForWrite(uint32_t offset, size_t len);
|
||||
|
||||
Reference in New Issue
Block a user