修复IWDG超时未配置与dhara resume回滚:看门狗误复位与复位后写入全部丢失,台架全量自检PASS
This commit is contained in:
+50
-16
@@ -10,6 +10,10 @@
|
||||
* v1.1 2026-08-28 王建锋 改为 TCP Server,迁入独立任务 timeSyncTask,
|
||||
* 所有 socket 操作经 net_socket 线程安全 API 走消息队列,
|
||||
* netTask 仅负责 net_poll/net_process_messages,多任务并发安全
|
||||
* v1.2 2026-10-02 王建锋 round 8b 消抖:等待片长 200ms→50ms,并把各处长
|
||||
* 等待(500/2000/200ms)统一走 time_sync_delay_fed()
|
||||
* 按 ≤50ms 分片、每片喂心跳——消除"心跳滑出两个连续
|
||||
* 100ms 抽样窗"的节拍抖动(round 7 台架 snap=0x17)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -38,9 +42,31 @@
|
||||
#define TIME_SYNC_TOTAL_BUDGET_MS 30000U
|
||||
|
||||
/* 看门狗分片等待:单次 net_recv_to 的等待片长上限。须显著小于看门狗抽样窗
|
||||
* (task_watchdog.c WD_POLL_PERIOD_MS=100ms)的容错窗口(8 窗 = 800ms),
|
||||
* 200ms 留足余量;语义上仅把一次长等待拆成多次短等待,总预算不变。 */
|
||||
#define TIME_SYNC_WAIT_SLICE_MS 200U
|
||||
* (task_watchdog.c WD_POLL_PERIOD_MS=100ms)——片长 ≤50ms 时每片前喂的心跳
|
||||
* 必然落在同一个 100ms 抽样窗内,消除"心跳恰好滑过两个连续窗口"的边界抖动
|
||||
* (round 7 台架稳态 snap=0x17 即抽样窗 vs 心跳节拍的良性错位,round 8b 消抖)。
|
||||
* 语义上仅把一次长等待拆成多次短等待,总预算不变。 */
|
||||
#define TIME_SYNC_WAIT_SLICE_MS 50U
|
||||
|
||||
/*
|
||||
* 函数功能:可喂心跳的延时(把长等待切成 ≤50ms 短片,每片喂一次心跳)
|
||||
* 入口参数:ms - 总延时(ms) uint32_t
|
||||
* 返回值:无
|
||||
* 限定条件:任务上下文调用
|
||||
* 函数说明:看门狗抽样窗为 100ms(task_watchdog.c WD_POLL_PERIOD_MS)。把任意长
|
||||
* 等待切成 ≤TIME_SYNC_WAIT_SLICE_MS 的短片、每片前喂心跳,使心跳必然
|
||||
* 落在单个抽样窗内——语义等价于一次长延时,仅把"心跳节奏"钉在窗内
|
||||
* (round 8b 消抖;不改变总延时预算)。
|
||||
*/
|
||||
static void time_sync_delay_fed(uint32_t ms) {
|
||||
while (ms > 0U) {
|
||||
uint32_t slice = (ms > TIME_SYNC_WAIT_SLICE_MS) ? TIME_SYNC_WAIT_SLICE_MS : ms;
|
||||
|
||||
task_wd_beat(TASK_WD_TIMESYNC);
|
||||
vTaskDelay(pdMS_TO_TICKS(slice));
|
||||
ms -= slice;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:创建并监听 TCP 时间同步服务端口
|
||||
@@ -59,7 +85,7 @@ static int time_sync_open_listener(void) {
|
||||
int s = net_socket(NET_AF_INET, NET_SOCK_STREAM);
|
||||
if (s < 0) {
|
||||
DBG_ERROR("time_sync: net_socket FAIL");
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
time_sync_delay_fed(500U);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -72,16 +98,14 @@ static int time_sync_open_listener(void) {
|
||||
if (net_bind(s, (struct net_sockaddr *)&addr, sizeof(addr)) != 0) {
|
||||
DBG_ERROR("time_sync: bind port %d FAIL", TIME_SYNC_PORT);
|
||||
net_close(s);
|
||||
task_wd_beat(TASK_WD_TIMESYNC);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
time_sync_delay_fed(2000U);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (net_listen(s) != 0) {
|
||||
DBG_ERROR("time_sync: listen FAIL");
|
||||
net_close(s);
|
||||
task_wd_beat(TASK_WD_TIMESYNC);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
time_sync_delay_fed(2000U);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -166,11 +190,24 @@ static void time_sync_handle_conn(int conn_sock) {
|
||||
void time_sync_task(void *argument) {
|
||||
(void)argument;
|
||||
|
||||
task_wd_bind(TASK_WD_TIMESYNC); /* FTL 心跳路由:登记本任务句柄(入口一次) */
|
||||
|
||||
/* 等网络栈真正就绪(取代拍脑袋的 8s 魔法延时),确保 netTask 已开始处理消息;
|
||||
* osFlagsNoClear:就绪位是状态,不能被本任务消费掉(否则其它等待者永不唤醒) */
|
||||
if (sys_evtHandle != NULL) {
|
||||
(void)osEventFlagsWait(sys_evtHandle, SYS_EVT_NET_READY,
|
||||
osFlagsWaitAny | osFlagsNoClear, osWaitForever);
|
||||
/* osFlagsNoClear:就绪位是状态,不能被本任务消费掉(否则其它等待者永不唤醒)。
|
||||
* 2026-10-02 台架修复:等待改 100ms 分片 + 每片喂心跳——IWDG 必需掩码含
|
||||
* TS 位,原 osWaitForever 无心跳 → 启动初期(存储已就绪、网络未就绪)
|
||||
* 掩码 800ms 不可达 → 停喂 → 复位循环(2026-10-02 台架根因之一)。
|
||||
* 100ms 分片 = 抽样窗,纯任务睡眠零队列开销。 */
|
||||
for (;;) {
|
||||
uint32_t r = osEventFlagsWait(sys_evtHandle, SYS_EVT_NET_READY,
|
||||
osFlagsWaitAny | osFlagsNoClear, 100u);
|
||||
if ((r & osFlagsError) == 0u) {
|
||||
break; /* NET_READY 已置位(状态位,未被消费) */
|
||||
}
|
||||
task_wd_beat(TASK_WD_TIMESYNC); /* 看门狗:分片喂心跳(屏障等待态) */
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
@@ -184,8 +221,7 @@ void time_sync_task(void *argument) {
|
||||
int ls = time_sync_open_listener();
|
||||
if (ls < 0) {
|
||||
DBG_ERROR("time_sync: open listener FAIL, retry later");
|
||||
task_wd_beat(TASK_WD_TIMESYNC);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
time_sync_delay_fed(2000U);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -198,8 +234,7 @@ void time_sync_task(void *argument) {
|
||||
net_close(ls); /* 网络重建:旧监听失效,回外层重建 */
|
||||
break;
|
||||
}
|
||||
task_wd_beat(TASK_WD_TIMESYNC);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
time_sync_delay_fed(200U);
|
||||
}
|
||||
} while (conn < 0);
|
||||
|
||||
@@ -211,7 +246,6 @@ void time_sync_task(void *argument) {
|
||||
time_sync_handle_conn(conn);
|
||||
/* conn(单连接模式下即 ls)已被 net_close 释放,下次循环重建监听 */
|
||||
|
||||
task_wd_beat(TASK_WD_TIMESYNC);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
time_sync_delay_fed(50U);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user