修复IWDG超时未配置与dhara resume回滚:看门狗误复位与复位后写入全部丢失,台架全量自检PASS

This commit is contained in:
2026-10-02 20:48:30 +08:00
parent d1a2eaab07
commit 930215f81a
33 changed files with 1875 additions and 94 deletions
+17 -5
View File
@@ -32,6 +32,7 @@
#include "dbg_log.h"
#include "net_socket.h"
#include "lftpd.h"
#include "task_watchdog.h"
#include "../test/board/ch395f_test_task.h"
#include "../test/board/ch395f_test.h" /* ENABLE_NET_LAYER_TESTS:netTask 条件创建 */
#include "time_sync.h"
@@ -235,21 +236,32 @@ void StartNetTask(void *argument)
__weak void StartFtpTask(void *argument)
{
/* USER CODE BEGIN StartFtpTask */
task_wd_bind(TASK_WD_FTP); /* FTL 心跳路由:登记本任务句柄(入口一次) */
/* 等网络 + 存储都真正就绪后再 listen,取代拍脑袋的 7s 魔法延时 */
/*
sys_evtHandle:等待哪个事件组
SYS_EVT_NET_READY | SYS_EVT_STORAGE_READY:要等哪几位(1u<<0 网络、1u<<1 存储)
osFlagsWaitAll:请求的位全部置位才唤醒(即"网络且存储都就绪")
osWaitForever:无限期等待,不设超时——任务会挂起(让出 CPU,零占用),直到生产者置位对应位才被唤醒
100u:单次等待分片时长——2026-10-02 台架修复由 osWaitForever 改为 100ms
分片循环:IWDG 必需掩码含 FTP 位,屏障等待态必须能喂心跳(见下方注释)
*/
if (sys_evtHandle != NULL) {
/* osFlagsNoClear 必须带:就绪位是**状态**不是命令,消费型等待会把位清掉,
* 导致后面 WaitAll(两位) 的等待者永远等不到(2026-09-21 实测:netTask 先
* 消费 STORAGE_READY、uiTask/timeSync 再消费 NET_READY → 本任务永不唤醒、
* FTP 21 端口从未监听)。 */
(void)osEventFlagsWait(sys_evtHandle,
SYS_EVT_NET_READY | SYS_EVT_STORAGE_READY,
osFlagsWaitAll | osFlagsNoClear, osWaitForever);
* FTP 21 端口从未监听)。
* 2026-10-02 台架修复:等待改 100ms 分片 + 每片喂心跳(与 timeSync/uiTask/
* netTask 入口同模式)——IWDG 必需掩码含 FTP 位,原 osWaitForever 无心跳,
* IWDG 启动(存储就绪)时网络未必就绪 → 掩码 800ms 不可达 → 停喂 → 复位循环 */
for (;;) {
uint32_t r = osEventFlagsWait(sys_evtHandle,
SYS_EVT_NET_READY | SYS_EVT_STORAGE_READY,
osFlagsWaitAll | osFlagsNoClear, 100u);
if ((r & osFlagsError) == 0u) {
break; /* 两位均就绪(状态位,未被消费) */
}
lftpd_task_wd_beat(); /* 看门狗:分片喂心跳(屏障等待态) */
}
}
lftpd_t ftp;
lftpd_start("/", 21, &ftp);
+18 -1
View File
@@ -39,6 +39,7 @@
#include "net_select.h"
#include "app_main.h"
#include "sys_clock.h"
#include "task_watchdog.h" /* task_wd_tick_probe():round 8b 时间源存活性取证 */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
@@ -83,6 +84,11 @@ int main(void)
{
/* USER CODE BEGIN 1 */
/* round 8b 取证:**必须在 HAL_Init() 之前**把上一轮的"时间源存活性"终值
* 快照到 .noinit 的 prev 槽——TIM7 在 HAL_Init 里就 HAL_TIM_Base_Start_IT
* 开始 1ms 中断,而开机上报要到 app_main_init(≈117ms)才跑;不先搬走,
* 上一轮终值会被本轮开机瞬间的 tick 覆盖(实机测试规划.md §0.5.4.3)。 */
task_wd_tick_snapshot();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
@@ -223,7 +229,18 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
/* round 8b 取证:TIM7 每 1ms 把"时间源存活性"写进复位不丢的 .noinit 槽
* (uwTick + 中断计数)。复位后由 task_wd_seg_report() 打 TICKRUN 行,
* 与"进段打点"时刻对比,判定 TIM7(HAL 时基)是否在冻结同刻停摆
* (实机测试规划.md §0.5.4.3)。
* ⚠ task_wd_tick_probe() 内不得调用任何 FreeRTOS API:TIM7 在 HAL_Init
* 阶段即开始中断,远早于调度器启动,此时 ISR 版内核 API 会触发 port.c 的
* 优先级断言并把系统卡死在本 ISR 内(2026-10-02 台架实测)。
* 放 USER CODE 区(L2):CubeMX 重生成不丢。 */
if (htim->Instance == TIM7)
{
task_wd_tick_probe();
}
/* USER CODE END Callback 1 */
}