fix(vd960DBN): OTA 刷写成功误判未启动 — 状态回 idle + 补 ota_report 主动上报
现场: 远程平台发起 OTA, 设备物理刷写成功 (70块全ACK, flash DONE), 但平台 ota_status 轮询只见 state=ready → 误判'刷写未启动'。 根因: 1. ota_flash_done 刷写成功后台侧状态置 READY (与协议状态机 'FLASHING──成功──▶IDLE(清槽/保留)' 不符), 平台无法区分 '待刷 ready' 与 '已刷完' → 持续 ready 判未启动 2. 固件漏实现协议 §5.5 ota_report 主动上报 (done/failed 重发 3次×5s), 平台收不到成功信号, 只能靠 ota_status 轮询兜底 修复 (协议 V1.09 + 固件): - 协议: 刷写成功状态明确回 idle (镜像保留, last_result=0, 可重刷); ota_report 升级为刷写结果主依据; 平台判定指引 (idle+size>0+last_result=0 =成功; 不得以轮询未见 flashing 或持续 ready 判未启动) - ota_srv.c: ota_flash_done → OTA_STATE_IDLE (镜像保留) + 上报 done; ota_flash_fail → 补 ota_report failed (保留 event_report 告警); ota_cmd_begin 兼容 idle+size/crc32 一致 → 直接回 ready (免下载重刷) - iot_mqtt_srv.c: 新增 ota_report 上报状态机 (立即首发 + 5s×3 重发, 同 msg_id/ts), 共享 _iot_pub_payload (event_report 复用, RAM 零新增) - 单测: test_flash_flow/test_flash_ready_timeout 断言 ota_report 上报, state 断言 READY→IDLE; 新增 test_begin_reflash; 10/10 全过 + 22 py 断言
This commit is contained in:
@@ -248,6 +248,13 @@ int ota_cmd_begin(uint32_t size, uint32_t crc32, const char *version, uint8_t fo
|
||||
/* 镜像已就绪, 平台可直接 ota_flash */
|
||||
return 0; /* data.offset = size */
|
||||
}
|
||||
if (_meta.state == OTA_STATE_IDLE) {
|
||||
/* V1.09: 刷写完成后的 idle 且镜像一致 → 直接回 ready, 免下载可重刷 */
|
||||
_meta.state = OTA_STATE_READY;
|
||||
ota_meta_write(&_meta);
|
||||
PRINT("OTA: begin idle+same image → ready (reflash)\n");
|
||||
return 0; /* data.offset = size */
|
||||
}
|
||||
if (_meta.state == OTA_STATE_DOWNLOADING) {
|
||||
_meta.state = OTA_STATE_DOWNLOADING;
|
||||
PRINT("OTA: begin resume received=%lu\n", (unsigned long)_meta.received);
|
||||
@@ -454,7 +461,7 @@ static void ota_send_9f(uint8_t sub_l, uint8_t sub_h, uint8_t cmd,
|
||||
UART2_SendString(_ota_buf.frame, (uint16_t)(5 + datalen + 1));
|
||||
}
|
||||
|
||||
/* 刷写失败收尾: 状态落盘 + event_report 告警 + 恢复 0x7F 模式 */
|
||||
/* 刷写失败收尾 (V1.09): 状态落盘 + ota_report failed + event_report 告警 + 恢复 0x7F 模式 */
|
||||
static void ota_flash_fail(uint32_t err)
|
||||
{
|
||||
PRINT("OTA: flash FAILED err=0x%lX\n", (unsigned long)err);
|
||||
@@ -467,16 +474,20 @@ static void ota_flash_fail(uint32_t err)
|
||||
g_flag_counter_ota.flag = 0;
|
||||
lup_frame_reset();
|
||||
_fs = OTA_FLASH_IDLE;
|
||||
/* ota_report stage=failed (平台判定主依据, V1.09) */
|
||||
extern void iot_ota_report_result(uint8_t ok, uint32_t err);
|
||||
iot_ota_report_result(0, err);
|
||||
/* event_report ota_error 告警 (平台必答, 由 iot_mqtt_srv 发送) */
|
||||
extern void iot_evt_report_ota_error(uint32_t err);
|
||||
iot_evt_report_ota_error(err);
|
||||
}
|
||||
|
||||
/* 刷写成功收尾: 保留镜像 (state=ready 可重刷), 恢复 0x7F 模式 */
|
||||
/* 刷写成功收尾 (V1.09): 状态回 idle 但镜像保留 (可重刷, last_result=0),
|
||||
上报 ota_report stage=done (平台判定主依据), 恢复 0x7F 模式 */
|
||||
static void ota_flash_done(void)
|
||||
{
|
||||
PRINT("OTA: flash DONE sent=%lu\n", (unsigned long)_fs_sent);
|
||||
_meta.state = OTA_STATE_READY;
|
||||
_meta.state = OTA_STATE_IDLE; /* V1.09: idle+size>0 = 已刷写完成 (区别于 ready=待刷) */
|
||||
_meta.last_result = 0;
|
||||
ota_meta_write(&_meta);
|
||||
offlog_ota_result(0);
|
||||
@@ -484,6 +495,9 @@ static void ota_flash_done(void)
|
||||
g_flag_counter_ota.flag = 0;
|
||||
lup_frame_reset();
|
||||
_fs = OTA_FLASH_IDLE;
|
||||
/* ota_report stage=done (平台判定主依据, V1.09) */
|
||||
extern void iot_ota_report_result(uint8_t ok, uint32_t err);
|
||||
iot_ota_report_result(1, 0);
|
||||
}
|
||||
|
||||
/* UART2 收到 bootloader 0x9F ACK 帧 (uart_srv OTA 分支调用, 主循环上下文)
|
||||
|
||||
Reference in New Issue
Block a user