From 127fed4b07379d741047e39b4bfda9ed5b9c87f6 Mon Sep 17 00:00:00 2001 From: wangfq Date: Thu, 23 Jul 2026 14:49:07 +0800 Subject: [PATCH] =?UTF-8?q?feat(vd960DBN):=20=E7=A1=AC=E4=BB=B6=20IWDG=20?= =?UTF-8?q?=E7=9C=8B=E9=97=A8=E7=8B=97=20+=20=E5=B9=B3=E5=8F=B0=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E8=B6=85=E6=97=B6=E9=87=8D=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 设计: 1. 硬件 IWDG: LSI≈40kHz, Prescaler=256, Reload=625 → ~4s 超时 主循环 iot_mqtt_poll() 每轮喂狗, 防死循环/硬故障 2. 平台响应看门狗: 3×心跳周期(180s)内无平台回复 → NVIC_SystemReset _iot_last_recv_ms 刷新点: - iot_handle_publish() — 收到平台任意 PUBLISH 命令 - iot_evt_handle_ack() — event_report 的 ACK - iot_handle_suback() — 刚连上 READY 时初始化计时 3. 仅在 IOT_STATE_READY 时检查 (未连上不触发) --- .../APP/include/iot_mqtt_srv.h | 3 ++ .../APP/iot_mqtt_srv.c | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/include/iot_mqtt_srv.h b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/include/iot_mqtt_srv.h index 105334c..21b1ed7 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/include/iot_mqtt_srv.h +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/include/iot_mqtt_srv.h @@ -21,6 +21,7 @@ #define IOT_MQTT_RECONNECT_MIN_MS 5000 // 最小重连间隔 #define IOT_MQTT_RECONNECT_MAX_MS 60000 // 最大重连间隔 (指数退避上限) #define IOT_MQTT_HEARTBEAT_MS 60000 // 心跳上报周期 (60s) +#define IOT_MQTT_WDT_TIMEOUT_MS 180000 // 平台响应看门狗: 3×心跳=180s 无回复→重启 #define IOT_MQTT_RECV_BUF_LEN 1024 // 接收缓冲区 (单次交互 ≤1024) #define IOT_MQTT_SEND_BUF_LEN 1024 // 发送缓冲区 (单次交互 ≤1024) #define IOT_MQTT_TOPIC_MAX_LEN 128 // Topic 最大长度 @@ -52,5 +53,7 @@ void iot_mqtt_poll(void); // 主循环轮询 (状态机 + 心跳 + void iot_mqtt_handle_sock_int(uint8_t socketid, uint8_t intstat); // Socket 中断处理 void iot_mqtt_publish_sensor(void); // 推送传感器数据到 MQTT void iot_evt_handle_ack(uint32_t msg_id, int code); // event_report 平台应答入口 (V1.04) +void iot_watchdog_kick(void); // 喂硬件 IWDG (主循环调用) +void iot_watchdog_check(void); // 平台响应超时检查 (180s无回复→重启) #endif /* __IOT_MQTT_SRV_H__ */ diff --git a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c index c7a77cc..abf27e8 100644 --- a/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c +++ b/vd960DBN/BLE/OnlyUpdateApp_Peripheral/APP/iot_mqtt_srv.c @@ -23,6 +23,7 @@ #include "simple_json.h" #include "tcp_json_srv.h" #include "storage.h" +#include "ch32v20x_iwdg.h" #include #include #include @@ -41,6 +42,7 @@ static uint32_t _iot_last_heartbeat = 0; // 上次心跳时刻 (ms) static uint32_t _iot_reconnect_deadline = 0; static uint32_t _iot_reconnect_backoff = 0; static uint32_t _iot_connect_start = 0; // TCP connect 开始时刻 +static uint32_t _iot_last_recv_ms = 0; // 上次收到平台回复时刻 (看门狗追踪) /*=========================================================================== * 传感器数据缓存 & 上报间隔控制 @@ -207,6 +209,7 @@ void iot_evt_handle_ack(uint32_t msg_id, int code) { return; } /* 确认成功 → 弹出本包事件 */ + _iot_last_recv_ms = mstick(); // 看门狗: 平台对 event_report 的 ACK 也算响应 _evt_head = (_evt_head + _evt_pend_n) % IOT_EVT_QUEUE_DEPTH; _evt_count -= _evt_pend_n; PRINT("EVT: ack ok, %d events dequeued (left=%d)\n", _evt_pend_n, _evt_count); @@ -395,6 +398,8 @@ static void iot_handle_publish(const char *topic, uint8_t *payload, int payload_ PRINT("IOT: PUBLISH topic=%s payload=%s\n", topic, json); + _iot_last_recv_ms = mstick(); // 看门狗: 收到平台任意消息即刷新 + /* 提取 msg_id 和 cmd */ char tmp[256]; uint32_t msg_id = 0; @@ -550,6 +555,7 @@ static void iot_handle_suback(void) { PRINT("IOT: ← SUBACK, topics subscribed\n"); g_iot_state = IOT_STATE_READY; _iot_reconnect_backoff = 0; // 连接成功, 重置退避 + _iot_last_recv_ms = mstick(); // 看门狗: 刚连上, 重置平台响应计时 // V1.03: 订阅成功后发布 initialize 告知服务器上线 (IoT 路径) iot_send_initialize(); @@ -898,10 +904,48 @@ void iot_mqtt_handle_sock_int(uint8_t socketid, uint8_t intstat) { } } +/*=========================================================================== + * 看门狗 — 硬件 IWDG + 平台响应超时 + * IWDG: ~4s LSI超时, 主循环喂狗, 防死循环/硬故障 + * 平台狗: 3×心跳周期(180s)无平台回复 → NVIC_SystemReset + *===========================================================================*/ + +/* IWDG 初始化: LSI≈40kHz, Prescaler=256 → 156Hz tick, Reload=625 → 4s 超时 */ +void iot_watchdog_init(void) { + IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); + IWDG_SetPrescaler(IWDG_Prescaler_256); + IWDG_SetReload(625); // 625 × (256/40000) ≈ 4.0s + IWDG_ReloadCounter(); + IWDG_Enable(); + PRINT("IOT: IWDG init ok, timeout≈4s\n"); +} + +/* 喂狗 — 主循环每轮调用 */ +void iot_watchdog_kick(void) { + IWDG_ReloadCounter(); +} + +/* 平台响应超时检查 — iot_mqtt_poll 中调用 */ +void iot_watchdog_check(void) { + if (g_iot_state != IOT_STATE_READY) return; + uint32_t now = mstick(); + if (now - _iot_last_recv_ms > IOT_MQTT_WDT_TIMEOUT_MS) { + PRINT("IOT: WATCHDOG no platform reply for %lu ms (>%u ms), resetting...\n", + (unsigned long)(now - _iot_last_recv_ms), IOT_MQTT_WDT_TIMEOUT_MS); + /* 不再喂狗, IWDG 4s 后自动复位; 或直接 NVIC_SystemReset */ + NVIC_SystemReset(); + } +} + /*=========================================================================== * 主循环轮询 *===========================================================================*/ void iot_mqtt_poll(void) { + iot_watchdog_kick(); // 喂硬件 IWDG + + /* 平台响应超时检查 */ + iot_watchdog_check(); + /* 断线重连 */ if (g_iot_state == IOT_STATE_DISCONNECTED && g_iot_socket == 0xFF) { if (_iot_reconnect_deadline == 0 || mstick() > _iot_reconnect_deadline) { @@ -974,4 +1018,7 @@ void iot_mqtt_init(void) { _iot_reconnect_backoff = 0; _iot_reconnect_deadline = mstick() + 2000; // 启动后 2s 开始首次连接 g_iot_state = IOT_STATE_DISCONNECTED; + + /* 初始化硬件看门狗 IWDG (LSI≈40kHz, 4s 超时, 主循环喂狗) */ + iot_watchdog_init(); }