实现独立看门狗:CubeMX 配置 IWDG + 任务心跳位图,恢复三处被覆盖定制

经 CubeMX 图形界面启用 IWDG(Prescaler=64 / Reload=1249,标称 2498ms /
最坏 1701ms),并落地心跳位图判定、各任务埋点、RCC_CSR 复位原因上报与
configASSERT 改造。重生成覆盖的既有定制已全部恢复。

P0(开机死循环):HAL_IWDG_Init() 内部立即启动看门狗,而 CubeMX 把
MX_IWDG_Init() 插在 app_main_init() 之前——该段 NAND/RTC/ADC 初始化耗时
数秒无喂狗点,按 2.5s 超时必然复位。改 Src/iwdg.c 为只填参数不启动,
启动移交 task_wd_start(),由 defaultTask 在存储 bring-up 完成后调用。

恢复的三处定制(重生成覆盖):
- Src/stm32f4xx_it.c:HardFault_Handler 崩溃现场采集被打回空 while(1)
- Inc/FreeRTOSConfig.h:栈溢出检测与堆失败钩子两个宏被整块删除
- Src/freertos.c:三处任务栈实测记录中文注释丢失(数值未丢)

新增:
- App/util/task_watchdog.{c,h}:心跳位图 + 抽样判定 + IWDG 延后启动
- time_sync.c 长等待切片:net_recv_to 单次可睡满 30s 预算,切成 200ms 片
- Src/main.c 复位原因锁存(读后即清 RMVF,防残留误判)

埋点:defaultTask(唯一喂狗者)/ netTask(含 PHY 等待循环)/ uiTask /
timeSyncTask。ftpTask 首期剔除掩码,待二期改 lftpd。

门禁:build 0 错误 0 警告;pre-commit 10 钩子全通过;Flash +2956B / RAM +40B。
This commit is contained in:
2026-09-29 07:22:04 +08:00
parent e18e9f2cfd
commit 7feeea6c56
24 changed files with 1761 additions and 361 deletions
+5
View File
@@ -37,6 +37,11 @@ MDK-ARM/RTE/
# STM32CubeMX (keep .ioc, it's the project source) # STM32CubeMX (keep .ioc, it's the project source)
# *.ioc # *.ioc
# CubeMX 重生成时自动产生的旧文件备份(Src/Backup/、Inc/Backup/)——
# 纯本地临时物,内容 = 重生成前的快照;入库只会造成无意义的提交抖动
Src/Backup/
Inc/Backup/
# Visual Studio / IDE # Visual Studio / IDE
.vs/ .vs/
.vscode/ .vscode/
+4 -4
View File
File diff suppressed because one or more lines are too long
+62
View File
@@ -28,6 +28,53 @@
/* g_rs485 由 rs485.c 定义,经 rs485.h 的 extern 引用;接收缓冲内聚于句柄 rx_buf */ /* g_rs485 由 rs485.c 定义,经 rs485.h 的 extern 引用;接收缓冲内聚于句柄 rx_buf */
/* 复位原因锁存值(Src/main.c 在 HAL_Init() 后立即写入并清除 RCC_CSR)。
* 放这里而非 main.c,是因为需要与其它应用级全局量同层、且日志侧更好引用。 */
volatile uint32_t g_rcc_csr_latched;
/*
* 函数功能:把 RCC_CSR 锁存值翻译为可读的复位原因串(见手册 RM0090 §6.3.22)
* 入口参数:csr - 锁存的 RCC_CSR 值
* buf - 输出缓冲
* len - 缓冲容量
* 返回值:无
* 函数说明:按"最可信归因"的优先级组织——IWDG/WWDG 优先于软件复位
* (看门狗复位是我们真正关心的自动恢复事件;软件复位多为崩溃钩子
* 兜底,两者同时置位时报告看门狗更有价值)。纯 ASCII,防编码坑。
*/
static void reset_cause_str(uint32_t csr, char *buf, unsigned int len) {
const char *cause;
if ((csr & RCC_CSR_IWDGRSTF) != 0u) {
cause = "IWDG (independent watchdog)";
} else if ((csr & RCC_CSR_WWDGRSTF) != 0u) {
cause = "WWDG (window watchdog)";
} else if ((csr & RCC_CSR_SFTRSTF) != 0u) {
cause = "software (NVIC_SystemReset)";
} else if ((csr & RCC_CSR_PORRSTF) != 0u) {
cause = "power-on (POR)";
} else if ((csr & RCC_CSR_PINRSTF) != 0u) {
cause = "external pin (NRST)";
} else if ((csr & RCC_CSR_BORRSTF) != 0u) {
cause = "brown-out (BOR)";
} else {
cause = "unknown";
}
/* 简单有界拼接(不引 snprintf,避免依赖与栈开销) */
if (buf == NULL || len == 0u) {
return;
}
{
unsigned int i = 0u;
while ((i < (len - 1u)) && (cause[i] != '\0')) {
buf[i] = cause[i];
i++;
}
buf[i] = '\0';
}
}
/* /*
* 函数功能:应用层初始化 * 函数功能:应用层初始化
* 入口参数:无 * 入口参数:无
@@ -46,6 +93,21 @@ int app_main_init(void) {
/* 日志引擎初始化(创建待发队列;须先于任何 syslog_post) */ /* 日志引擎初始化(创建待发队列;须先于任何 syslog_post) */
(void)syslog_mcu_init(); (void)syslog_mcu_init();
/* 0) 复位原因上报(锁存值由 Src/main.c 在 HAL_Init() 后立即采得)。
* 放在日志引擎之后、业务初始化之前:任何一次非上电复位都值得在
* 开机第一时间看到——尤其 IWDG,它意味着上一轮运行有任务卡死。
* 注意:RCC_CSR 已被 main.c 清零,本处只读锁存副本。 */
{
char cause[40];
uint32_t csr = g_rcc_csr_latched;
reset_cause_str(csr, cause, sizeof(cause));
DBG_INFO("reset cause: %s (CSR=0x%08lX)", cause, (unsigned long)csr);
/* 看门狗复位记入自检记录(只记载故障,符合既有约定) */
if ((csr & (RCC_CSR_IWDGRSTF | RCC_CSR_WWDGRSTF)) != 0u) {
syslog_post(SYSLOG_SELFTEST, "watchdog reset");
}
}
/* /*
* 1) 时间子系统初始化(尽早完成,后续所有日志带时间戳) * 1) 时间子系统初始化(尽早完成,后续所有日志带时间戳)
* sd2506_init() 从 RTC 读取初始时间 * sd2506_init() 从 RTC 读取初始时间
+26 -2
View File
@@ -17,6 +17,7 @@
#include "net_socket.h" #include "net_socket.h"
#include "sys_clock.h" #include "sys_clock.h"
#include "sys_events.h" #include "sys_events.h"
#include "task_watchdog.h"
#define DBG_TAG "[TIME_SYNC]" #define DBG_TAG "[TIME_SYNC]"
#include "dbg_log.h" #include "dbg_log.h"
@@ -36,6 +37,11 @@
*/ */
#define TIME_SYNC_TOTAL_BUDGET_MS 30000U #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
/* /*
* 函数功能:创建并监听 TCP 时间同步服务端口 * 函数功能:创建并监听 TCP 时间同步服务端口
* 入口参数:无 * 入口参数:无
@@ -49,6 +55,7 @@ static int time_sync_open_listener(void) {
int retry; int retry;
for (retry = 0; retry < 5; retry++) { for (retry = 0; retry < 5; retry++) {
task_wd_beat(TASK_WD_TIMESYNC); /* 每次重试前喂心跳(见下方 500ms/2000ms 延时) */
int s = net_socket(NET_AF_INET, NET_SOCK_STREAM); int s = net_socket(NET_AF_INET, NET_SOCK_STREAM);
if (s < 0) { if (s < 0) {
DBG_ERROR("time_sync: net_socket FAIL"); DBG_ERROR("time_sync: net_socket FAIL");
@@ -65,6 +72,7 @@ static int time_sync_open_listener(void) {
if (net_bind(s, (struct net_sockaddr *)&addr, sizeof(addr)) != 0) { if (net_bind(s, (struct net_sockaddr *)&addr, sizeof(addr)) != 0) {
DBG_ERROR("time_sync: bind port %d FAIL", TIME_SYNC_PORT); DBG_ERROR("time_sync: bind port %d FAIL", TIME_SYNC_PORT);
net_close(s); net_close(s);
task_wd_beat(TASK_WD_TIMESYNC);
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
continue; continue;
} }
@@ -72,6 +80,7 @@ static int time_sync_open_listener(void) {
if (net_listen(s) != 0) { if (net_listen(s) != 0) {
DBG_ERROR("time_sync: listen FAIL"); DBG_ERROR("time_sync: listen FAIL");
net_close(s); net_close(s);
task_wd_beat(TASK_WD_TIMESYNC);
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
continue; continue;
} }
@@ -99,7 +108,11 @@ static void time_sync_handle_conn(int conn_sock) {
while (got < (int)sizeof(buf)) { while (got < (int)sizeof(buf)) {
/* 单次预算 = 剩余总预算(L3 pending:等待期 netTask 零占用,调用方 /* 单次预算 = 剩余总预算(L3 pending:等待期 netTask 零占用,调用方
* 在自己上下文睡任务通知,旧片间 vTaskDelay(1) 让出退役) */ * 在自己上下文睡任务通知,旧片间 vTaskDelay(1) 让出退役)
* ⚠ 看门狗约束:本任务在 required_mask 内,而单次 net_recv_to 可睡满
* 30s 预算 —— 等待期必须周期性喂心跳,否则"对端连上但不发时间包"这种
* 完全正常的场景会被判为任务卡死(见设计说明 §4.4 长耗时白名单)。
* 做法:把长等待切成 WD 窗口内的短片(片长 ≤200ms),每片先喂心跳。 */
TickType_t elapsed = xTaskGetTickCount() - t0; TickType_t elapsed = xTaskGetTickCount() - t0;
uint32_t rem = (elapsed >= (TickType_t)pdMS_TO_TICKS(TIME_SYNC_TOTAL_BUDGET_MS)) ? 0U uint32_t rem = (elapsed >= (TickType_t)pdMS_TO_TICKS(TIME_SYNC_TOTAL_BUDGET_MS)) ? 0U
: (uint32_t)((TickType_t)TIME_SYNC_TOTAL_BUDGET_MS - elapsed); : (uint32_t)((TickType_t)TIME_SYNC_TOTAL_BUDGET_MS - elapsed);
@@ -107,6 +120,10 @@ static void time_sync_handle_conn(int conn_sock) {
DBG_INFO("time_sync: no TIME packet in 30s, drop conn"); DBG_INFO("time_sync: no TIME packet in 30s, drop conn");
break; /* 总预算耗尽(语义同旧 30s 超时) */ break; /* 总预算耗尽(语义同旧 30s 超时) */
} }
task_wd_beat(TASK_WD_TIMESYNC);
if (rem > TIME_SYNC_WAIT_SLICE_MS) {
rem = TIME_SYNC_WAIT_SLICE_MS; /* 分片:等待期保持心跳节奏 */
}
int n = net_recv_to(conn_sock, buf + got, (int)(sizeof(buf) - got), rem); int n = net_recv_to(conn_sock, buf + got, (int)(sizeof(buf) - got), rem);
if (n > 0) { if (n > 0) {
got += n; got += n;
@@ -119,7 +136,7 @@ static void time_sync_handle_conn(int conn_sock) {
break; /* 对端关闭(EOF) */ break; /* 对端关闭(EOF) */
} }
if (n == -2) { if (n == -2) {
continue; /* 本次预算等满无数据 → 下轮 rem=0 退出 */ continue; /* 本片预算等满无数据 → 下一片重算剩余预算 */
} }
break; /* 真错误 */ break; /* 真错误 */
} }
@@ -157,12 +174,17 @@ void time_sync_task(void *argument) {
} }
for (;;) { for (;;) {
/* 心跳:本任务在 required_mask 内。以下每一处可能长于 100ms 抽样窗的
* 阻塞点(监听重试 2s、accept 轮询 200ms/次、收尾 50ms)都就近补心跳。 */
task_wd_beat(TASK_WD_TIMESYNC);
/* 记录本次监听对应的网络代次;代次变化(网络重建)则放弃旧监听重建 */ /* 记录本次监听对应的网络代次;代次变化(网络重建)则放弃旧监听重建 */
uint32_t gen = net_get_generation(); uint32_t gen = net_get_generation();
int ls = time_sync_open_listener(); int ls = time_sync_open_listener();
if (ls < 0) { if (ls < 0) {
DBG_ERROR("time_sync: open listener FAIL, retry later"); DBG_ERROR("time_sync: open listener FAIL, retry later");
task_wd_beat(TASK_WD_TIMESYNC);
vTaskDelay(pdMS_TO_TICKS(2000)); vTaskDelay(pdMS_TO_TICKS(2000));
continue; continue;
} }
@@ -176,6 +198,7 @@ void time_sync_task(void *argument) {
net_close(ls); /* 网络重建:旧监听失效,回外层重建 */ net_close(ls); /* 网络重建:旧监听失效,回外层重建 */
break; break;
} }
task_wd_beat(TASK_WD_TIMESYNC);
vTaskDelay(pdMS_TO_TICKS(200)); vTaskDelay(pdMS_TO_TICKS(200));
} }
} while (conn < 0); } while (conn < 0);
@@ -188,6 +211,7 @@ void time_sync_task(void *argument) {
time_sync_handle_conn(conn); time_sync_handle_conn(conn);
/* conn(单连接模式下即 ls)已被 net_close 释放,下次循环重建监听 */ /* conn(单连接模式下即 ls)已被 net_close 释放,下次循环重建监听 */
task_wd_beat(TASK_WD_TIMESYNC);
vTaskDelay(pdMS_TO_TICKS(50)); vTaskDelay(pdMS_TO_TICKS(50));
} }
} }
+13
View File
@@ -30,6 +30,7 @@
#include "sys_log.h" #include "sys_log.h"
#include "sys_events.h" #include "sys_events.h"
#include "dbg_log.h" #include "dbg_log.h"
#include "task_watchdog.h"
/* 任务句柄与属性块(CubeMX 生成全局,定义于 Src/freertos.c): /* 任务句柄与属性块(CubeMX 生成全局,定义于 Src/freertos.c):
* 栈水位观测需 6 任务句柄 + 属性块 stack_size(配置栈大小的唯一定义处) */ * 栈水位观测需 6 任务句柄 + 属性块 stack_size(配置栈大小的唯一定义处) */
@@ -149,7 +150,19 @@ void default_task_func(void *argument) {
* 并让脏指针无法再进入 HAL_UART_Transmit 的缓冲遍历。 */ * 并让脏指针无法再进入 HAL_UART_Transmit 的缓冲遍历。 */
dbg_console_writer_attach(); dbg_console_writer_attach();
/* 启动看门狗(延后启动):此处位于全部长耗时初始化之后——存储 bring-up 深链
* (mount/mkfs/FAT 探针/syslog 挂载/配置加载)已完成,监视一开始即处于稳态。
* 这正是"启动段不喂狗、主循环段才喂"的落点(见 docs/子系统设计/看门狗设计说明.md
* §4.5 决策 C):MX_IWDG_Init() 只填参数不启动,启动延后到此时。
* 代价(显式声明):从复位到此处约数秒的窗口无看门狗保护,该段死机表现为
* "无任何输出 + LED 不闪",可人工辨识。 */
task_wd_start();
for (;;) { for (;;) {
/* 心跳抽样与喂狗判定(内部节流至 100ms;全员到位才喂,否则累计停喂) */
task_wd_poll();
/* 本任务自己的心跳 */
task_wd_beat(TASK_WD_DEFAULT);
/* 等待"保存网络配置"或"控制台待发":任一即醒;无事件 50ms 后返回 /* 等待"保存网络配置"或"控制台待发":任一即醒;无事件 50ms 后返回
* (日志时延 = 事件唤醒,实测无丢失;50ms 兜底仅防事件位异常) */ * (日志时延 = 事件唤醒,实测无丢失;50ms 兜底仅防事件位异常) */
if (sys_evtHandle != NULL) { if (sys_evtHandle != NULL) {
+12
View File
@@ -28,6 +28,7 @@
#include "sys_events.h" #include "sys_events.h"
#include "sys_log.h" #include "sys_log.h"
#include "test_config.h" /* 测试模式宏(ENABLE_HW_LAYER_TESTS);产品构建全未定义,无作用 */ #include "test_config.h" /* 测试模式宏(ENABLE_HW_LAYER_TESTS);产品构建全未定义,无作用 */
#include "task_watchdog.h"
#define DBG_TAG "[NET_TASK]" #define DBG_TAG "[NET_TASK]"
#include "dbg_log.h" #include "dbg_log.h"
@@ -112,6 +113,10 @@ int net_stack_bring_up(void) {
if (phy != CH395F_PHY_DISCONN) { if (phy != CH395F_PHY_DISCONN) {
break; break;
} }
/* 心跳埋点:本循环单次最长约 1.1s(含 PHY 仍未就绪的 60 次迭代里
* 每次 50ms 延时叠加),远超看门狗 100ms 抽样窗——必须在延时段补心跳,
* 否则 PHY 未插网线时本任务会被误判为卡死(见设计说明 §4.4 长耗时白名单) */
task_wd_beat(TASK_WD_NET);
osDelay(50); osDelay(50);
} }
DBG_INFO("PHY: %s", DBG_INFO("PHY: %s",
@@ -166,6 +171,9 @@ void net_task_func(void const *arg) {
#if defined(ENABLE_HW_LAYER_TESTS) #if defined(ENABLE_HW_LAYER_TESTS)
DBG_INFO("netTask parked: HW-layer test mode, CH395F owned by testTask"); DBG_INFO("netTask parked: HW-layer test mode, CH395F owned by testTask");
for (;;) { for (;;) {
/* 该模式下本任务已被 task_wd_required_mask() 剔除,喂心跳无副作用;
* 保留埋点以免掩码配置变更时意外误杀 */
task_wd_beat(TASK_WD_NET);
osDelay(1000); osDelay(1000);
} }
#endif #endif
@@ -196,6 +204,10 @@ void net_task_func(void const *arg) {
/* ==================== 主轮询循环 ==================== */ /* ==================== 主轮询循环 ==================== */
for (;;) { for (;;) {
/* 心跳:本任务在监视掩码内(ENABLE_HW_LAYER_TESTS 下由 task_wd_required_mask
* 剔除,本埋点无副作用) */
task_wd_beat(TASK_WD_NET);
/* UI 保存网口配置后请求立即应用:在此重建网络(新 IP/掩码/网关/MAC)。 /* UI 保存网口配置后请求立即应用:在此重建网络(新 IP/掩码/网关/MAC)。
* 重建完成后代次号已递增,各 TCP 服务据此重建监听;期间连接会断开(预期)。 */ * 重建完成后代次号已递增,各 TCP 服务据此重建监听;期间连接会断开(预期)。 */
if (sys_evtHandle != NULL if (sys_evtHandle != NULL
+7
View File
@@ -21,6 +21,7 @@
#include "sys_clock.h" #include "sys_clock.h"
#include "test_config.h" /* TEST_LATENCY_PROBE(链路时延探针编译开关) */ #include "test_config.h" /* TEST_LATENCY_PROBE(链路时延探针编译开关) */
#include "net_latency_test.h" /* M3 探针:ui_loop(生产循环实测周期) */ #include "net_latency_test.h" /* M3 探针:ui_loop(生产循环实测周期) */
#include "task_watchdog.h"
/* /*
* 函数功能:待机屏底部时钟提供回调(平台差异:MCU = sys_clock_get_str) * 函数功能:待机屏底部时钟提供回调(平台差异:MCU = sys_clock_get_str)
@@ -63,6 +64,9 @@ static void ui_task_wait_net_ready(void) {
void ui_task_func(void *argument) { void ui_task_func(void *argument) {
(void)argument; (void)argument;
/* 等待网络就绪期间不可能喂狗:本任务此时尚未进入主循环,而就绪位由 netTask 置位。
* 该段若长期不成立,看门狗会复位——这是期望行为(网络 bring-up 卡死须暴露)。
* 注意本任务在 required_mask 内,主循环跑起来后须保证每 100ms 窗口内至少喂一次。 */
DBG_INFO("UI task: started, wait net ready"); DBG_INFO("UI task: started, wait net ready");
ui_task_wait_net_ready(); ui_task_wait_net_ready();
DBG_INFO("UI task: net ready, init port"); DBG_INFO("UI task: net ready, init port");
@@ -108,6 +112,9 @@ void ui_task_func(void *argument) {
#endif #endif
ui_port_step(10); ui_port_step(10);
ui_net_sink_poll(); ui_net_sink_poll();
/* 心跳:ui_port_step 内含 LVGL 渲染,单轮耗时可能逼近 10ms 量级;
* 100ms 抽样窗内可容纳多轮,此埋点足够 */
task_wd_beat(TASK_WD_UI);
osDelay(10); osDelay(10);
} }
} }
+201
View File
@@ -0,0 +1,201 @@
/*
* 模块名称:Task Watchdog(IWDG + 任务心跳位图)
* 模块功能:把独立看门狗(IWDG)与"全部任务存活"绑定,使单任务死锁/饿死/
* 断言挂死可自动复位恢复,而非人工断电。
* 核心语义:喂狗 = "所有被监视任务都在抽样窗口内动过"。
* 适用平台:STM32F407ZGTx + FreeRTOS(CMSIS-RTOS V2)
* 作者:王建锋
* 创建日期:2026-09-29
* 修改记录:
* v1.0 2026-09-29 王建锋 创建:心跳位图 + 抽样判定 + IWDG 延后启动
*
* 设计依据:docs/子系统设计/看门狗设计说明.md
* - §3.1 为何不用"每任务各自喂狗"(那只检测全系统同时挂死)
* - §3.3 为何用"单字位图 + 取走清零"(免临界区,天然原子)
* - §4.3 超时与窗口的取值推导(含 LSI 偏快 47kHz 的最坏情况校验)
* - §4.5 为何由 defaultTask 在 bring-up 完成后启动
* - §5.3 为何"停喂"而不直接 NVIC_SystemReset(保留 IWDGRSTF 权威归因)
*
* ⚠ 本模块不创建任何 FreeRTOS/CMSIS-RTOS 对象,可安全用于内核启动前后的上下文。
*/
#include "task_watchdog.h"
#include "main.h" /* HAL_GetTick()(HAL 时基 = TIM7,1ms) */
#include "iwdg.h" /* hiwdg 参数来源(CubeMX 生成,见 Src/iwdg.c) */
#define DBG_TAG "[WD]"
#include "dbg_log.h"
/* Private defines -----------------------------------------------------------*/
/* 抽样周期:defaultTask 主循环为 50ms 基准,100ms 是其整数倍(见 §4.3) */
#define WD_POLL_PERIOD_MS 100u
/* 连续未达标容忍次数:8 × 100ms = 800ms。
* 需容纳 NAND 擦写(最坏数百 ms)等长耗时操作,同时远小于 IWDG 最坏超时
* 1701ms,保证"停喂后仍能复上电"(§4.3 的包含关系) */
#define WD_MISS_TOLERANCE 8u
/* IWDG 超时参数:PR=4 → 64 分频;RLR=1249
* 标称 64 × 1249 / 32000 ≈ 2498 ms
* 最坏 64 × 1249 / 47000 ≈ 1701 ms(LSI 偏快时超时变短,按最坏校核) */
#define WD_IWDG_PRESCALER 4u
#define WD_IWDG_RELOAD 1249u
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* 心跳位图:各任务只置位,校验者"取走并清零"。
* 单字读-改-写在 Cortex-M4 上天然原子,无需临界区(§3.3) */
static volatile uint32_t s_hb_bits;
static uint32_t s_miss_streak; /* 连续未达标轮数(达到容忍上限即停喂) */
static uint32_t s_miss_total; /* 累计未达标轮数(观测用) */
static uint32_t s_last_mask; /* 上次抽样到的位图(定位卡死任务用) */
static uint32_t s_started; /* 1 = IWDG 已启动 */
/* Private function prototypes -----------------------------------------------*/
static uint32_t wd_required_mask(void);
/* Private functions ---------------------------------------------------------*/
/*
* 函数功能:必需心跳位掩码(编译期按构建配置生成)
* 入口参数:无
* 返回值:本次构建要求"必须动过"的任务位集合
* 限定条件:无
* 函数说明:按 §4.1/§4.2 的设计,监视范围随构建配置变化:
* - testTask 仅在启用测试套件时创建
* - netTask 在 ENABLE_HW_LAYER_TESTS 下入口即自挂起(不干活),
* 不要求其心跳,否则该构建永不喂狗
* 注:ftpTask 当前统一纳入(其主循环为 lftpd 事件循环,需在
* lftpd 侧埋点;若某构建下 ftpTask 不创建,句柄检查兜底)。
*/
static uint32_t wd_required_mask(void) {
uint32_t m = (1u << (uint32_t)TASK_WD_DEFAULT)
| (1u << (uint32_t)TASK_WD_NET)
| (1u << (uint32_t)TASK_WD_FTP)
| (1u << (uint32_t)TASK_WD_UI)
| (1u << (uint32_t)TASK_WD_TIMESYNC);
/* netTask 自挂起(CH395F 由 testTask 独占):不要求心跳 */
#if defined(ENABLE_HW_LAYER_TESTS)
m &= ~(1u << (uint32_t)TASK_WD_NET);
#endif
return m;
}
/* Public functions ----------------------------------------------------------*/
/*
* 函数功能:任务心跳置位
* 入口参数:id - 任务 ID(见 task_watchdog.h)
* 返回值:无
* 限定条件:可在任意上下文调用(单字写,无内核对象依赖)
* 函数说明:各任务在自己的主循环里调用。仅 1~2 条指令。
*/
void task_wd_beat(task_wd_id_t id) {
if ((uint32_t)id < (uint32_t)TASK_WD_ID_MAX) {
s_hb_bits |= (1u << (uint32_t)id);
}
}
/*
* 函数功能:启动 IWDG(延后启动,由 defaultTask 在 bring-up 完成后调用)
* 入口参数:无
* 返回值:无
* 限定条件:仅 defaultTask 调用;须在 osKernelStart 之后(本函数只用 HAL/寄存器)
* 函数说明:MX_IWDG_Init() 已把参数填入全局 hiwdg(Prescaler/Reload 由 CubeMX
* 在 Src/iwdg.c 生成区维护),但不启动(见该文件 IWDG_DEFER_START 注释)。
* 此处才真正写 IWDG_Key 启动——使"启动段不喂狗"成立(§4.5)。
* IWDG 一旦启动不可停,只能靠复位终止。
*/
void task_wd_start(void) {
if (s_started != 0u) {
return;
}
s_started = 1u;
/* 启动前先喂一次:让首个抽样窗口从"启动时刻"起算,
* 而非从 MX_IWDG_Init 的时刻起算(避免启动后立即超时) */
IWDG->KR = 0x0000AAAAu; /* 重装计数器(喂狗) */
IWDG->KR = 0x0000CCCCu; /* 启动看门狗 */
DBG_INFO("[WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms");
}
/*
* 函数功能:心跳抽样与喂狗判定(defaultTask 主循环调用)
* 入口参数:无
* 返回值:无
* 限定条件:仅 defaultTask 主循环调用(唯一喂狗者);内部节流到 100ms 一次
* 函数说明:取走并清零位图 → 与必需掩码比较:
* 全中 → 清零缺失计数并喂狗;
* 有缺 → 累计;连续达到 WD_MISS_TOLERANCE 次后**停止喂狗**,
* 让 IWDG 自然溢出复位(这样 RCC_CSR 记录的是权威的
* IWDGRSTF,而不是 NVIC_SystemReset 留下的 SFTRSTF —— §5.3)。
*/
void task_wd_poll(void) {
static uint32_t s_last_tick;
uint32_t now;
uint32_t snapshot;
if (s_started == 0u) {
return; /* 未启动:不做任何判定 */
}
now = HAL_GetTick();
if ((now - s_last_tick) < WD_POLL_PERIOD_MS) {
return; /* 节流:非 100ms 边界直接返回 */
}
s_last_tick = now;
snapshot = s_hb_bits; /* 读 */
s_hb_bits = 0u; /* 清:语义 = "自上次抽样以来谁动过" */
s_last_mask = snapshot;
if (snapshot == wd_required_mask()) {
s_miss_streak = 0u;
IWDG->KR = 0x0000AAAAu; /* 全员健康:喂狗 */
return;
}
/* 有任务缺席:累计(不喂狗) */
s_miss_total++;
if (s_miss_streak < WD_MISS_TOLERANCE) {
s_miss_streak++;
}
if (s_miss_streak >= WD_MISS_TOLERANCE) {
/* 连续 800ms 有任务未动过 → 已停喂 → 约 2.5s 后 IWDG 复位。
* 最后遗言走裸 UART(不依赖内核、不遍历指针、有界长度)。 */
DBG_ERROR("[WD] task stall: mask=0x%08X req=0x%08X miss=%lu",
(unsigned)snapshot,
(unsigned)wd_required_mask(),
(unsigned long)s_miss_total);
}
}
/*
* 函数功能:读上次抽样到的位图(观测/自检用)
*/
uint32_t task_wd_last_mask(void) {
return s_last_mask;
}
/*
* 函数功能:读累计未达标轮数(观测/自检用)
*/
uint32_t task_wd_miss_count(void) {
return s_miss_total;
}
/*
* 函数功能:查询 IWDG 是否已启动(观测/自检用)
*/
uint32_t task_wd_is_armed(void) {
return (s_started != 0u) ? 1u : 0u;
}
+76
View File
@@ -0,0 +1,76 @@
/*
* 模块名称:Task Watchdog(IWDG + 任务心跳位图)
* 模块功能:独立看门狗与"全部任务存活"绑定的对外接口
* 适用平台:STM32F407ZGTx + FreeRTOS(CMSIS-RTOS V2)
* 作者:王建锋
* 创建日期:2026-09-29
* 修改记录:
* v1.0 2026-09-29 王建锋 创建
*
* 设计依据:docs/子系统设计/看门狗设计说明.md
*/
#ifndef TASK_WATCHDOG_H
#define TASK_WATCHDOG_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* 任务 ID(位序号 = 心跳位图上的位置,与必需掩码一一对应)
* 顺序一旦确定不要插空/改动,掩码是编译期常量
*/
typedef enum {
TASK_WD_DEFAULT = 0,
TASK_WD_NET = 1,
TASK_WD_FTP = 2,
TASK_WD_TEST = 3,
TASK_WD_UI = 4,
TASK_WD_TIMESYNC = 5,
TASK_WD_ID_MAX
} task_wd_id_t;
/*
* 函数功能:任务心跳置位(各任务在自己主循环里调用)
* 入口参数:id - 任务 ID
* 返回值:无
* 限定条件:任意上下文可调(单字原子写、无内核对象依赖)
* 函数说明:仅 1~2 条指令,无锁、无阻塞,可放在中断外任意位置。
*/
void task_wd_beat(task_wd_id_t id);
/*
* 函数功能:启动 IWDG(**延后启动**)
* 入口参数:无
* 返回值:无
* 限定条件:仅 defaultTask 在存储 bring-up 完成后调用一次
* 函数说明:MX_IWDG_Init() 只填参数不启动(原因见 Src/iwdg.c 的
* IWDG_DEFER_START 注释:HAL_IWDG_Init 内部会立即启动,而它被
* CubeMX 插在 app_main_init 之前,那段无喂狗点且耗时可达数秒)。
* 本函数才真正启动,使"启动段不喂狗、主循环段才喂"成立。
*/
void task_wd_start(void);
/*
* 函数功能:心跳抽样与喂狗判定
* 入口参数:无
* 返回值:无
* 限定条件:仅 defaultTask 主循环调用(唯一喂狗者)
* 函数说明:内部节流至 100ms 一次。全员到位才喂狗;连续 800ms 有任务
* 缺席则停止喂狗,由 IWDG 自然溢出复位(保留 IWDGRSTF 权威归因)。
*/
void task_wd_poll(void);
/* 观测接口(自检 / 串口报告用) */
uint32_t task_wd_last_mask(void); /* 上次抽样到的位图(0 位 = 缺席任务) */
uint32_t task_wd_miss_count(void); /* 累计未达标轮数 */
uint32_t task_wd_is_armed(void); /* 1 = IWDG 已启动 */
#ifdef __cplusplus
}
#endif
#endif /* TASK_WATCHDOG_H */
@@ -0,0 +1,220 @@
/**
******************************************************************************
* @file stm32f4xx_hal_iwdg.h
* @author MCD Application Team
* @brief Header file of IWDG HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32F4xx_HAL_IWDG_H
#define STM32F4xx_HAL_IWDG_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal_def.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
/** @defgroup IWDG IWDG
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup IWDG_Exported_Types IWDG Exported Types
* @{
*/
/**
* @brief IWDG Init structure definition
*/
typedef struct
{
uint32_t Prescaler; /*!< Select the prescaler of the IWDG.
This parameter can be a value of @ref IWDG_Prescaler */
uint32_t Reload; /*!< Specifies the IWDG down-counter reload value.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x0FFF */
} IWDG_InitTypeDef;
/**
* @brief IWDG Handle Structure definition
*/
typedef struct
{
IWDG_TypeDef *Instance; /*!< Register base address */
IWDG_InitTypeDef Init; /*!< IWDG required parameters */
} IWDG_HandleTypeDef;
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup IWDG_Exported_Constants IWDG Exported Constants
* @{
*/
/** @defgroup IWDG_Prescaler IWDG Prescaler
* @{
*/
#define IWDG_PRESCALER_4 0x00000000u /*!< IWDG prescaler set to 4 */
#define IWDG_PRESCALER_8 IWDG_PR_PR_0 /*!< IWDG prescaler set to 8 */
#define IWDG_PRESCALER_16 IWDG_PR_PR_1 /*!< IWDG prescaler set to 16 */
#define IWDG_PRESCALER_32 (IWDG_PR_PR_1 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 32 */
#define IWDG_PRESCALER_64 IWDG_PR_PR_2 /*!< IWDG prescaler set to 64 */
#define IWDG_PRESCALER_128 (IWDG_PR_PR_2 | IWDG_PR_PR_0) /*!< IWDG prescaler set to 128 */
#define IWDG_PRESCALER_256 (IWDG_PR_PR_2 | IWDG_PR_PR_1) /*!< IWDG prescaler set to 256 */
/**
* @}
*/
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/** @defgroup IWDG_Exported_Macros IWDG Exported Macros
* @{
*/
/**
* @brief Enable the IWDG peripheral.
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define __HAL_IWDG_START(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_ENABLE)
/**
* @brief Reload IWDG counter with value defined in the reload register
* (write access to IWDG_PR and IWDG_RLR registers disabled).
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define __HAL_IWDG_RELOAD_COUNTER(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_RELOAD)
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup IWDG_Exported_Functions IWDG Exported Functions
* @{
*/
/** @defgroup IWDG_Exported_Functions_Group1 Initialization and Start functions
* @{
*/
/* Initialization/Start functions ********************************************/
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg);
/**
* @}
*/
/** @defgroup IWDG_Exported_Functions_Group2 IO operation functions
* @{
*/
/* I/O operation functions ****************************************************/
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg);
/**
* @}
*/
/**
* @}
*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup IWDG_Private_Constants IWDG Private Constants
* @{
*/
/**
* @brief IWDG Key Register BitMask
*/
#define IWDG_KEY_RELOAD 0x0000AAAAu /*!< IWDG Reload Counter Enable */
#define IWDG_KEY_ENABLE 0x0000CCCCu /*!< IWDG Peripheral Enable */
#define IWDG_KEY_WRITE_ACCESS_ENABLE 0x00005555u /*!< IWDG KR Write Access Enable */
#define IWDG_KEY_WRITE_ACCESS_DISABLE 0x00000000u /*!< IWDG KR Write Access Disable */
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup IWDG_Private_Macros IWDG Private Macros
* @{
*/
/**
* @brief Enable write access to IWDG_PR and IWDG_RLR registers.
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define IWDG_ENABLE_WRITE_ACCESS(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_WRITE_ACCESS_ENABLE)
/**
* @brief Disable write access to IWDG_PR and IWDG_RLR registers.
* @param __HANDLE__ IWDG handle
* @retval None
*/
#define IWDG_DISABLE_WRITE_ACCESS(__HANDLE__) WRITE_REG((__HANDLE__)->Instance->KR, IWDG_KEY_WRITE_ACCESS_DISABLE)
/**
* @brief Check IWDG prescaler value.
* @param __PRESCALER__ IWDG prescaler value
* @retval None
*/
#define IS_IWDG_PRESCALER(__PRESCALER__) (((__PRESCALER__) == IWDG_PRESCALER_4) || \
((__PRESCALER__) == IWDG_PRESCALER_8) || \
((__PRESCALER__) == IWDG_PRESCALER_16) || \
((__PRESCALER__) == IWDG_PRESCALER_32) || \
((__PRESCALER__) == IWDG_PRESCALER_64) || \
((__PRESCALER__) == IWDG_PRESCALER_128)|| \
((__PRESCALER__) == IWDG_PRESCALER_256))
/**
* @brief Check IWDG reload value.
* @param __RELOAD__ IWDG reload value
* @retval None
*/
#define IS_IWDG_RELOAD(__RELOAD__) ((__RELOAD__) <= IWDG_RLR_RL)
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* STM32F4xx_HAL_IWDG_H */
@@ -0,0 +1,302 @@
/**
******************************************************************************
* @file stm32f4xx_ll_iwdg.h
* @author MCD Application Team
* @brief Header file of IWDG LL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32F4xx_LL_IWDG_H
#define STM32F4xx_LL_IWDG_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
/** @addtogroup STM32F4xx_LL_Driver
* @{
*/
#if defined(IWDG)
/** @defgroup IWDG_LL IWDG
* @{
*/
/* Private types -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup IWDG_LL_Private_Constants IWDG Private Constants
* @{
*/
#define LL_IWDG_KEY_RELOAD 0x0000AAAAU /*!< IWDG Reload Counter Enable */
#define LL_IWDG_KEY_ENABLE 0x0000CCCCU /*!< IWDG Peripheral Enable */
#define LL_IWDG_KEY_WR_ACCESS_ENABLE 0x00005555U /*!< IWDG KR Write Access Enable */
#define LL_IWDG_KEY_WR_ACCESS_DISABLE 0x00000000U /*!< IWDG KR Write Access Disable */
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup IWDG_LL_Exported_Constants IWDG Exported Constants
* @{
*/
/** @defgroup IWDG_LL_EC_GET_FLAG Get Flags Defines
* @brief Flags defines which can be used with LL_IWDG_ReadReg function
* @{
*/
#define LL_IWDG_SR_PVU IWDG_SR_PVU /*!< Watchdog prescaler value update */
#define LL_IWDG_SR_RVU IWDG_SR_RVU /*!< Watchdog counter reload value update */
/**
* @}
*/
/** @defgroup IWDG_LL_EC_PRESCALER Prescaler Divider
* @{
*/
#define LL_IWDG_PRESCALER_4 0x00000000U /*!< Divider by 4 */
#define LL_IWDG_PRESCALER_8 (IWDG_PR_PR_0) /*!< Divider by 8 */
#define LL_IWDG_PRESCALER_16 (IWDG_PR_PR_1) /*!< Divider by 16 */
#define LL_IWDG_PRESCALER_32 (IWDG_PR_PR_1 | IWDG_PR_PR_0) /*!< Divider by 32 */
#define LL_IWDG_PRESCALER_64 (IWDG_PR_PR_2) /*!< Divider by 64 */
#define LL_IWDG_PRESCALER_128 (IWDG_PR_PR_2 | IWDG_PR_PR_0) /*!< Divider by 128 */
#define LL_IWDG_PRESCALER_256 (IWDG_PR_PR_2 | IWDG_PR_PR_1) /*!< Divider by 256 */
/**
* @}
*/
/**
* @}
*/
/* Exported macro ------------------------------------------------------------*/
/** @defgroup IWDG_LL_Exported_Macros IWDG Exported Macros
* @{
*/
/** @defgroup IWDG_LL_EM_WRITE_READ Common Write and read registers Macros
* @{
*/
/**
* @brief Write a value in IWDG register
* @param __INSTANCE__ IWDG Instance
* @param __REG__ Register to be written
* @param __VALUE__ Value to be written in the register
* @retval None
*/
#define LL_IWDG_WriteReg(__INSTANCE__, __REG__, __VALUE__) WRITE_REG(__INSTANCE__->__REG__, (__VALUE__))
/**
* @brief Read a value in IWDG register
* @param __INSTANCE__ IWDG Instance
* @param __REG__ Register to be read
* @retval Register value
*/
#define LL_IWDG_ReadReg(__INSTANCE__, __REG__) READ_REG(__INSTANCE__->__REG__)
/**
* @}
*/
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @defgroup IWDG_LL_Exported_Functions IWDG Exported Functions
* @{
*/
/** @defgroup IWDG_LL_EF_Configuration Configuration
* @{
*/
/**
* @brief Start the Independent Watchdog
* @note Except if the hardware watchdog option is selected
* @rmtoll KR KEY LL_IWDG_Enable
* @param IWDGx IWDG Instance
* @retval None
*/
__STATIC_INLINE void LL_IWDG_Enable(IWDG_TypeDef *IWDGx)
{
WRITE_REG(IWDGx->KR, LL_IWDG_KEY_ENABLE);
}
/**
* @brief Reloads IWDG counter with value defined in the reload register
* @rmtoll KR KEY LL_IWDG_ReloadCounter
* @param IWDGx IWDG Instance
* @retval None
*/
__STATIC_INLINE void LL_IWDG_ReloadCounter(IWDG_TypeDef *IWDGx)
{
WRITE_REG(IWDGx->KR, LL_IWDG_KEY_RELOAD);
}
/**
* @brief Enable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers
* @rmtoll KR KEY LL_IWDG_EnableWriteAccess
* @param IWDGx IWDG Instance
* @retval None
*/
__STATIC_INLINE void LL_IWDG_EnableWriteAccess(IWDG_TypeDef *IWDGx)
{
WRITE_REG(IWDGx->KR, LL_IWDG_KEY_WR_ACCESS_ENABLE);
}
/**
* @brief Disable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers
* @rmtoll KR KEY LL_IWDG_DisableWriteAccess
* @param IWDGx IWDG Instance
* @retval None
*/
__STATIC_INLINE void LL_IWDG_DisableWriteAccess(IWDG_TypeDef *IWDGx)
{
WRITE_REG(IWDGx->KR, LL_IWDG_KEY_WR_ACCESS_DISABLE);
}
/**
* @brief Select the prescaler of the IWDG
* @rmtoll PR PR LL_IWDG_SetPrescaler
* @param IWDGx IWDG Instance
* @param Prescaler This parameter can be one of the following values:
* @arg @ref LL_IWDG_PRESCALER_4
* @arg @ref LL_IWDG_PRESCALER_8
* @arg @ref LL_IWDG_PRESCALER_16
* @arg @ref LL_IWDG_PRESCALER_32
* @arg @ref LL_IWDG_PRESCALER_64
* @arg @ref LL_IWDG_PRESCALER_128
* @arg @ref LL_IWDG_PRESCALER_256
* @retval None
*/
__STATIC_INLINE void LL_IWDG_SetPrescaler(IWDG_TypeDef *IWDGx, uint32_t Prescaler)
{
WRITE_REG(IWDGx->PR, IWDG_PR_PR & Prescaler);
}
/**
* @brief Get the selected prescaler of the IWDG
* @rmtoll PR PR LL_IWDG_GetPrescaler
* @param IWDGx IWDG Instance
* @retval Returned value can be one of the following values:
* @arg @ref LL_IWDG_PRESCALER_4
* @arg @ref LL_IWDG_PRESCALER_8
* @arg @ref LL_IWDG_PRESCALER_16
* @arg @ref LL_IWDG_PRESCALER_32
* @arg @ref LL_IWDG_PRESCALER_64
* @arg @ref LL_IWDG_PRESCALER_128
* @arg @ref LL_IWDG_PRESCALER_256
*/
__STATIC_INLINE uint32_t LL_IWDG_GetPrescaler(const IWDG_TypeDef *IWDGx)
{
return (READ_REG(IWDGx->PR));
}
/**
* @brief Specify the IWDG down-counter reload value
* @rmtoll RLR RL LL_IWDG_SetReloadCounter
* @param IWDGx IWDG Instance
* @param Counter Value between Min_Data=0 and Max_Data=0x0FFF
* @retval None
*/
__STATIC_INLINE void LL_IWDG_SetReloadCounter(IWDG_TypeDef *IWDGx, uint32_t Counter)
{
WRITE_REG(IWDGx->RLR, IWDG_RLR_RL & Counter);
}
/**
* @brief Get the specified IWDG down-counter reload value
* @rmtoll RLR RL LL_IWDG_GetReloadCounter
* @param IWDGx IWDG Instance
* @retval Value between Min_Data=0 and Max_Data=0x0FFF
*/
__STATIC_INLINE uint32_t LL_IWDG_GetReloadCounter(const IWDG_TypeDef *IWDGx)
{
return (READ_REG(IWDGx->RLR));
}
/**
* @}
*/
/** @defgroup IWDG_LL_EF_FLAG_Management FLAG_Management
* @{
*/
/**
* @brief Check if flag Prescaler Value Update is set or not
* @rmtoll SR PVU LL_IWDG_IsActiveFlag_PVU
* @param IWDGx IWDG Instance
* @retval State of bit (1 or 0).
*/
__STATIC_INLINE uint32_t LL_IWDG_IsActiveFlag_PVU(const IWDG_TypeDef *IWDGx)
{
return ((READ_BIT(IWDGx->SR, IWDG_SR_PVU) == (IWDG_SR_PVU)) ? 1UL : 0UL);
}
/**
* @brief Check if flag Reload Value Update is set or not
* @rmtoll SR RVU LL_IWDG_IsActiveFlag_RVU
* @param IWDGx IWDG Instance
* @retval State of bit (1 or 0).
*/
__STATIC_INLINE uint32_t LL_IWDG_IsActiveFlag_RVU(const IWDG_TypeDef *IWDGx)
{
return ((READ_BIT(IWDGx->SR, IWDG_SR_RVU) == (IWDG_SR_RVU)) ? 1UL : 0UL);
}
/**
* @brief Check if flags Prescaler & Reload Value Update are reset or not
* @rmtoll SR PVU LL_IWDG_IsReady\n
* SR RVU LL_IWDG_IsReady
* @param IWDGx IWDG Instance
* @retval State of bits (1 or 0).
*/
__STATIC_INLINE uint32_t LL_IWDG_IsReady(const IWDG_TypeDef *IWDGx)
{
return ((READ_BIT(IWDGx->SR, IWDG_SR_PVU | IWDG_SR_RVU) == 0U) ? 1UL : 0UL);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* IWDG */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* STM32F4xx_LL_IWDG_H */
@@ -0,0 +1,263 @@
/**
******************************************************************************
* @file stm32f4xx_hal_iwdg.c
* @author MCD Application Team
* @brief IWDG HAL module driver.
* This file provides firmware functions to manage the following
* functionalities of the Independent Watchdog (IWDG) peripheral:
* + Initialization and Start functions
* + IO operation functions
*
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
@verbatim
==============================================================================
##### IWDG Generic features #####
==============================================================================
[..]
(+) The IWDG can be started by either software or hardware (configurable
through option byte).
(+) The IWDG is clocked by the Low-Speed Internal clock (LSI) and thus stays
active even if the main clock fails.
(+) Once the IWDG is started, the LSI is forced ON and both cannot be
disabled. The counter starts counting down from the reset value (0xFFF).
When it reaches the end of count value (0x000) a reset signal is
generated (IWDG reset).
(+) Whenever the key value 0x0000 AAAA is written in the IWDG_KR register,
the IWDG_RLR value is reloaded into the counter and the watchdog reset
is prevented.
(+) The IWDG is implemented in the VDD voltage domain that is still functional
in STOP and STANDBY mode (IWDG reset can wake up the CPU from STANDBY).
IWDGRST flag in RCC_CSR register can be used to inform when an IWDG
reset occurs.
(+) Debug mode: When the microcontroller enters debug mode (core halted),
the IWDG counter either continues to work normally or stops, depending
on DBG_IWDG_STOP configuration bit in DBG module, accessible through
__HAL_DBGMCU_FREEZE_IWDG() and __HAL_DBGMCU_UNFREEZE_IWDG() macros.
[..] Min-max timeout value @32KHz (LSI): ~125us / ~32.7s
The IWDG timeout may vary due to LSI clock frequency dispersion.
STM32F4xx devices provide the capability to measure the LSI clock
frequency (LSI clock is internally connected to TIM5 CH4 input capture).
The measured value can be used to have an IWDG timeout with an
acceptable accuracy.
[..] Default timeout value (necessary for IWDG_SR status register update):
Constant LSI_VALUE is defined based on the nominal LSI clock frequency.
This frequency being subject to variations as mentioned above, the
default timeout value (defined through constant HAL_IWDG_DEFAULT_TIMEOUT
below) may become too short or too long.
In such cases, this default timeout value can be tuned by redefining
the constant LSI_VALUE at user-application level (based, for instance,
on the measured LSI clock frequency as explained above).
##### How to use this driver #####
==============================================================================
[..]
(#) Use IWDG using HAL_IWDG_Init() function to :
(++) Enable instance by writing Start keyword in IWDG_KEY register. LSI
clock is forced ON and IWDG counter starts counting down.
(++) Enable write access to configuration registers:
IWDG_PR and IWDG_RLR.
(++) Configure the IWDG prescaler and counter reload value. This reload
value will be loaded in the IWDG counter each time the watchdog is
reloaded, then the IWDG will start counting down from this value.
(++) Wait for status flags to be reset.
(#) Then the application program must refresh the IWDG counter at regular
intervals during normal operation to prevent an MCU reset, using
HAL_IWDG_Refresh() function.
*** IWDG HAL driver macros list ***
====================================
[..]
Below the list of most used macros in IWDG HAL driver:
(+) __HAL_IWDG_START: Enable the IWDG peripheral
(+) __HAL_IWDG_RELOAD_COUNTER: Reloads IWDG counter with value defined in
the reload register
@endverbatim
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
/** @addtogroup STM32F4xx_HAL_Driver
* @{
*/
#ifdef HAL_IWDG_MODULE_ENABLED
/** @addtogroup IWDG
* @brief IWDG HAL module driver.
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup IWDG_Private_Defines IWDG Private Defines
* @{
*/
/* Status register needs up to 5 LSI clock periods divided by the clock
prescaler to be updated. The number of LSI clock periods is upper-rounded to
6 for the timeout value calculation.
The timeout value is calculated using the highest prescaler (256) and
the LSI_VALUE constant. The value of this constant can be changed by the user
to take into account possible LSI clock period variations.
The timeout value is multiplied by 1000 to be converted in milliseconds.
LSI startup time is also considered here by adding LSI_STARTUP_TIME
converted in milliseconds. */
#define HAL_IWDG_DEFAULT_TIMEOUT (((6UL * 256UL * 1000UL) / (LSI_VALUE / 128U)) + \
((LSI_STARTUP_TIME / 1000UL) + 1UL))
#define IWDG_KERNEL_UPDATE_FLAGS (IWDG_SR_RVU | IWDG_SR_PVU)
/**
* @}
*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup IWDG_Exported_Functions
* @{
*/
/** @addtogroup IWDG_Exported_Functions_Group1
* @brief Initialization and Start functions.
*
@verbatim
===============================================================================
##### Initialization and Start functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Initialize the IWDG according to the specified parameters in the
IWDG_InitTypeDef of associated handle.
(+) Once initialization is performed in HAL_IWDG_Init function, Watchdog
is reloaded in order to exit function with correct time base.
@endverbatim
* @{
*/
/**
* @brief Initialize the IWDG according to the specified parameters in the
* IWDG_InitTypeDef and start watchdog. Before exiting function,
* watchdog is refreshed in order to have correct time base.
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
* the configuration information for the specified IWDG module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
{
uint32_t tickstart;
/* Check the IWDG handle allocation */
if (hiwdg == NULL)
{
return HAL_ERROR;
}
/* Check the parameters */
assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));
assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));
assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));
/* Enable IWDG. LSI is turned on automatically */
__HAL_IWDG_START(hiwdg);
/* Enable write access to IWDG_PR and IWDG_RLR registers by writing
0x5555 in KR */
IWDG_ENABLE_WRITE_ACCESS(hiwdg);
/* Write to IWDG registers the Prescaler & Reload values to work with */
hiwdg->Instance->PR = hiwdg->Init.Prescaler;
hiwdg->Instance->RLR = hiwdg->Init.Reload;
/* Check pending flag, if previous update not done, return timeout */
tickstart = HAL_GetTick();
/* Wait for register to be updated */
while ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
{
if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT)
{
if ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
{
return HAL_TIMEOUT;
}
}
}
/* Reload IWDG counter with value defined in the reload register */
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
/* Return function status */
return HAL_OK;
}
/**
* @}
*/
/** @addtogroup IWDG_Exported_Functions_Group2
* @brief IO operation functions
*
@verbatim
===============================================================================
##### IO operation functions #####
===============================================================================
[..] This section provides functions allowing to:
(+) Refresh the IWDG.
@endverbatim
* @{
*/
/**
* @brief Refresh the IWDG.
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
* the configuration information for the specified IWDG module.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
{
/* Reload IWDG counter with value defined in the reload register */
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
/* Return function status */
return HAL_OK;
}
/**
* @}
*/
/**
* @}
*/
#endif /* HAL_IWDG_MODULE_ENABLED */
/**
* @}
*/
/**
* @}
*/
+12 -2
View File
@@ -81,7 +81,8 @@
/* 栈溢出机械检测(2026-09-20 存储套件死机事故后加):模式 2 在每次上下文切换 /* 栈溢出机械检测(2026-09-20 存储套件死机事故后加):模式 2 在每次上下文切换
* 检查栈底水位线,溢出即调 vApplicationStackOverflowHook(报任务名+复位)。 * 检查栈底水位线,溢出即调 vApplicationStackOverflowHook(报任务名+复位)。
* 关闭检测时溢出会静默腐蚀堆相邻块(其它任务栈/TCB),表现为无异常、不可定位 * 关闭检测时溢出会静默腐蚀堆相邻块(其它任务栈/TCB),表现为无异常、不可定位
* 的全系统冻结——本次事故签名。开销:每次切换一次字比较,可忽略。 */ * 的全系统冻结——本次事故签名。开销:每次切换一次字比较,可忽略。
* ⚠ 本段为手工添加,CubeMX 重生成会删除(2026-09-29 实测),改完须核对本块存在 */
#define configCHECK_FOR_STACK_OVERFLOW 2 #define configCHECK_FOR_STACK_OVERFLOW 2
/* pvPortMalloc 失败钩子(只告警不复位:分配失败路径由各调用点 NULL 检查处理) */ /* pvPortMalloc 失败钩子(只告警不复位:分配失败路径由各调用点 NULL 检查处理) */
#define configUSE_MALLOC_FAILED_HOOK 1 #define configUSE_MALLOC_FAILED_HOOK 1
@@ -160,7 +161,16 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
/* Normal assert() semantics without relying on the provision of an assert.h /* Normal assert() semantics without relying on the provision of an assert.h
header file. */ header file. */
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
#define configASSERT( x ) if ((x) == 0) {taskDISABLE_INTERRUPTS(); for( ;; );} /* ⚠ 本段为手工添加,CubeMX 重生成会删除(2026-09-29 实测),改完须核对本块存在。
*
* 断言失败处理(2026-09-29,配合 IWDG):
* 原实现 `taskDISABLE_INTERRUPTS(); for(;;);` = 关中断死循环——CPU 停摆、无输出、
* 只能人工断电;且关中断后 IWDG 仍在跑(IWDG 走 LSI,与本 CPU 中断无关),
* 只要喂狗者(defaultTask)也被这该死循环卡住,2.5s 后 IWDG 自动复位,
* 系统自恢复。故改为调用带输出的上报函数(打印断言位置后主动复位)。
* 若断言发生在 IWDG 启动之前的启动段(无看门狗兜底),上报函数自行复位。 */
void vApplicationAssertFailed(const char *file, long line);
#define configASSERT( x ) if ((x) == 0) { vApplicationAssertFailed(__FILE__, __LINE__); }
/* USER CODE END 1 */ /* USER CODE END 1 */
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+51
View File
@@ -0,0 +1,51 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file iwdg.h
* @brief This file contains all the function prototypes for
* the iwdg.c file
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __IWDG_H__
#define __IWDG_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern IWDG_HandleTypeDef hiwdg;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_IWDG_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __IWDG_H__ */
+1 -1
View File
@@ -55,7 +55,7 @@
/* #define HAL_HASH_MODULE_ENABLED */ /* #define HAL_HASH_MODULE_ENABLED */
#define HAL_I2C_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED
/* #define HAL_I2S_MODULE_ENABLED */ /* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */ #define HAL_IWDG_MODULE_ENABLED
/* #define HAL_LTDC_MODULE_ENABLED */ /* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */ /* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */ /* #define HAL_RTC_MODULE_ENABLED */
+196 -267
View File
@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?> <?xml version="1.0" encoding="UTF-8"?>
<Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="project_projx.xsd"> <Project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" noNamespaceSchemaLocation="project_projx.xsd">
<SchemaVersion>2.1</SchemaVersion> <SchemaVersion>2.1</SchemaVersion>
<Header>### uVision Project, (C) Keil Software</Header> <Header>### uVision Project, (C) Keil Software</Header>
<Targets> <Targets>
<Target> <Target>
<TargetName>STM32F407-Demo</TargetName> <TargetName>STM32F407-Demo</TargetName>
@@ -19,28 +16,28 @@
<PackID>Keil.STM32F4xx_DFP.3.1.1</PackID> <PackID>Keil.STM32F4xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL> <PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001BFFF) IRAM2(0x2001C000-0x2001FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu> <Cpu>IRAM(0x20000000-0x2001BFFF) IRAM2(0x2001C000-0x2001FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) FPU2 CPUTYPE("Cortex-M4") TZ</Cpu>
<FlashUtilSpec></FlashUtilSpec> <FlashUtilSpec />
<StartupFile></StartupFile> <StartupFile />
<FlashDriverDll></FlashDriverDll> <FlashDriverDll />
<DeviceId>0</DeviceId> <DeviceId>0</DeviceId>
<RegisterFile></RegisterFile> <RegisterFile />
<MemoryEnv></MemoryEnv> <MemoryEnv />
<Cmp></Cmp> <Cmp />
<Asm></Asm> <Asm />
<Linker></Linker> <Linker />
<OHString></OHString> <OHString />
<InfinionOptionDll></InfinionOptionDll> <InfinionOptionDll />
<SLE66CMisc></SLE66CMisc> <SLE66CMisc />
<SLE66AMisc></SLE66AMisc> <SLE66AMisc />
<SLE66LinkerMisc></SLE66LinkerMisc> <SLE66LinkerMisc />
<SFDFile>$$Device:STM32F407ZGTx$CMSIS\SVD\STM32F407.svd</SFDFile> <SFDFile>$$Device:STM32F407ZGTx$CMSIS\SVD\STM32F407.svd</SFDFile>
<bCustSvd>0</bCustSvd> <bCustSvd>0</bCustSvd>
<UseEnv>0</UseEnv> <UseEnv>0</UseEnv>
<BinPath></BinPath> <BinPath />
<IncludePath></IncludePath> <IncludePath />
<LibPath></LibPath> <LibPath />
<RegisterFilePath></RegisterFilePath> <RegisterFilePath />
<DBRegisterFilePath></DBRegisterFilePath> <DBRegisterFilePath />
<TargetStatus> <TargetStatus>
<Error>0</Error> <Error>0</Error>
<ExitCodeStop>0</ExitCodeStop> <ExitCodeStop>0</ExitCodeStop>
@@ -55,15 +52,15 @@
<CreateHexFile>1</CreateHexFile> <CreateHexFile>1</CreateHexFile>
<DebugInformation>1</DebugInformation> <DebugInformation>1</DebugInformation>
<BrowseInformation>1</BrowseInformation> <BrowseInformation>1</BrowseInformation>
<ListingPath></ListingPath> <ListingPath />
<HexFormatSelection>1</HexFormatSelection> <HexFormatSelection>1</HexFormatSelection>
<Merge32K>0</Merge32K> <Merge32K>0</Merge32K>
<CreateBatchFile>0</CreateBatchFile> <CreateBatchFile>0</CreateBatchFile>
<BeforeCompile> <BeforeCompile>
<RunUserProg1>0</RunUserProg1> <RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2> <RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name> <UserProg1Name />
<UserProg2Name></UserProg2Name> <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopU1X>0</nStopU1X> <nStopU1X>0</nStopU1X>
@@ -72,8 +69,8 @@
<BeforeMake> <BeforeMake>
<RunUserProg1>0</RunUserProg1> <RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2> <RunUserProg2>0</RunUserProg2>
<UserProg1Name></UserProg1Name> <UserProg1Name />
<UserProg2Name></UserProg2Name> <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopB1X>0</nStopB1X> <nStopB1X>0</nStopB1X>
@@ -82,15 +79,15 @@
<AfterMake> <AfterMake>
<RunUserProg1>0</RunUserProg1> <RunUserProg1>0</RunUserProg1>
<RunUserProg2>1</RunUserProg2> <RunUserProg2>1</RunUserProg2>
<UserProg1Name></UserProg1Name> <UserProg1Name />
<UserProg2Name></UserProg2Name> <UserProg2Name />
<UserProg1Dos16Mode>0</UserProg1Dos16Mode> <UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode> <UserProg2Dos16Mode>0</UserProg2Dos16Mode>
<nStopA1X>0</nStopA1X> <nStopA1X>0</nStopA1X>
<nStopA2X>0</nStopA2X> <nStopA2X>0</nStopA2X>
</AfterMake> </AfterMake>
<SelectedForBatchBuild>1</SelectedForBatchBuild> <SelectedForBatchBuild>1</SelectedForBatchBuild>
<SVCSIdString></SVCSIdString> <SVCSIdString />
</TargetCommonOption> </TargetCommonOption>
<CommonProperty> <CommonProperty>
<UseCPPCompiler>0</UseCPPCompiler> <UseCPPCompiler>0</UseCPPCompiler>
@@ -104,8 +101,8 @@
<AssembleAssemblyFile>0</AssembleAssemblyFile> <AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly> <PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode> <StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument> <CustomArgument />
<IncludeLibraryModules></IncludeLibraryModules> <IncludeLibraryModules />
<ComprImg>0</ComprImg> <ComprImg>0</ComprImg>
</CommonProperty> </CommonProperty>
<DllOption> <DllOption>
@@ -139,10 +136,10 @@
<bUseTDR>1</bUseTDR> <bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2> <Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3>"" ()</Flash3> <Flash3>"" ()</Flash3>
<Flash4></Flash4> <Flash4 />
<pFcarmOut></pFcarmOut> <pFcarmOut />
<pFcarmGrp></pFcarmGrp> <pFcarmGrp />
<pFcArmRoot></pFcArmRoot> <pFcArmRoot />
<FcArmLst>0</FcArmLst> <FcArmLst>0</FcArmLst>
</Utilities> </Utilities>
<TargetArmAds> <TargetArmAds>
@@ -175,7 +172,7 @@
<RvctClst>0</RvctClst> <RvctClst>0</RvctClst>
<GenPPlst>0</GenPPlst> <GenPPlst>0</GenPPlst>
<AdsCpuType>"Cortex-M4"</AdsCpuType> <AdsCpuType>"Cortex-M4"</AdsCpuType>
<RvctDeviceName></RvctDeviceName> <RvctDeviceName />
<mOS>0</mOS> <mOS>0</mOS>
<uocRom>0</uocRom> <uocRom>0</uocRom>
<uocRam>0</uocRam> <uocRam>0</uocRam>
@@ -309,7 +306,7 @@
<Size>0x0</Size> <Size>0x0</Size>
</OCR_RVCT10> </OCR_RVCT10>
</OnChipMemories> </OnChipMemories>
<RvctStartVector></RvctStartVector> <RvctStartVector />
</ArmAdsMisc> </ArmAdsMisc>
<Cads> <Cads>
<interw>1</interw> <interw>1</interw>
@@ -338,7 +335,7 @@
<VariousControls> <VariousControls>
<MiscControls>--diag_suppress=1,68,111,188,191,546,1293</MiscControls> <MiscControls>--diag_suppress=1,68,111,188,191,546,1293</MiscControls>
<Define>USE_HAL_DRIVER,STM32F407xx,NDEBUG</Define> <Define>USE_HAL_DRIVER,STM32F407xx,NDEBUG</Define>
<Undefine></Undefine> <Undefine />
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../Drivers/BSP/NET/lftpd;../Drivers/BSP/NETCFG;../App;../App/app;../App/cfg;../App/log;../App/sync;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs;../test/board;../Lib/lvgl;../Drivers/BSP/UI;../Lib</IncludePath> <IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../Drivers/BSP/NET/lftpd;../Drivers/BSP/NETCFG;../App;../App/app;../App/cfg;../App/log;../App/sync;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs;../test/board;../Lib/lvgl;../Drivers/BSP/UI;../Lib</IncludePath>
</VariousControls> </VariousControls>
</Cads> </Cads>
@@ -354,9 +351,9 @@
<useXO>0</useXO> <useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls />
<Define></Define> <Define />
<Undefine></Undefine> <Undefine />
<IncludePath>../Drivers/CMSIS/Include</IncludePath> <IncludePath>../Drivers/CMSIS/Include</IncludePath>
</VariousControls> </VariousControls>
</Aads> </Aads>
@@ -367,15 +364,15 @@
<noStLib>0</noStLib> <noStLib>0</noStLib>
<RepFail>1</RepFail> <RepFail>1</RepFail>
<useFile>1</useFile> <useFile>1</useFile>
<TextAddressRange></TextAddressRange> <TextAddressRange />
<DataAddressRange></DataAddressRange> <DataAddressRange />
<pXoBase></pXoBase> <pXoBase />
<ScatterFile>STM32F407-Demo\STM32F407-Demo.sct</ScatterFile> <ScatterFile>STM32F407-Demo\STM32F407-Demo.sct</ScatterFile>
<IncludeLibs></IncludeLibs> <IncludeLibs />
<IncludeLibsPath></IncludeLibsPath> <IncludeLibsPath />
<Misc></Misc> <Misc />
<LinkerInputFile></LinkerInputFile> <LinkerInputFile />
<DisabledWarnings></DisabledWarnings> <DisabledWarnings />
</LDads> </LDads>
</TargetArmAds> </TargetArmAds>
</TargetOption> </TargetOption>
@@ -420,8 +417,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -449,12 +444,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -476,8 +465,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -505,12 +492,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -532,8 +513,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -561,16 +540,70 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
</File> </File>
<File>
<FileName>iwdg.c</FileName>
<FileType>1</FileType>
<FilePath>../Src/iwdg.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
</Cads>
<Aads>
<interw>2</interw>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<thumb>2</thumb>
<SplitLS>2</SplitLS>
<SwStkChk>2</SwStkChk>
<NoWarn>2</NoWarn>
<uSurpInc>2</uSurpInc>
<useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt>
</Aads>
</FileArmAds>
</FileOption>
</File>
<File> <File>
<FileName>spi.c</FileName> <FileName>spi.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -588,8 +621,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -617,12 +648,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -644,8 +669,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -673,12 +696,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -710,8 +727,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -739,12 +754,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -784,6 +793,11 @@
<FileType>1</FileType> <FileType>1</FileType>
<FilePath>..\App\util\sys_clock.c</FilePath> <FilePath>..\App\util\sys_clock.c</FilePath>
</File> </File>
<File>
<FileName>task_watchdog.c</FileName>
<FileType>1</FileType>
<FilePath>..\App\util\task_watchdog.c</FilePath>
</File>
<File> <File>
<FileName>time_sync.c</FileName> <FileName>time_sync.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -826,8 +840,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -855,12 +867,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -882,8 +888,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -911,12 +915,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1003,8 +1001,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1032,12 +1028,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1059,8 +1049,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1088,16 +1076,70 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
</File> </File>
<File>
<FileName>stm32f4xx_hal_iwdg.c</FileName>
<FileType>1</FileType>
<FilePath>../Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_iwdg.c</FilePath>
<FileOption>
<CommonProperty>
<UseCPPCompiler>2</UseCPPCompiler>
<RVCTCodeConst>0</RVCTCodeConst>
<RVCTZI>0</RVCTZI>
<RVCTOtherData>0</RVCTOtherData>
<ModuleSelection>0</ModuleSelection>
<IncludeInBuild>1</IncludeInBuild>
<AlwaysBuild>2</AlwaysBuild>
<GenerateAssemblyFile>2</GenerateAssemblyFile>
<AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode>
<ComprImg>1</ComprImg>
</CommonProperty>
<FileArmAds>
<Cads>
<interw>2</interw>
<Optim>0</Optim>
<oTime>2</oTime>
<SplitLS>2</SplitLS>
<OneElfS>2</OneElfS>
<Strict>2</Strict>
<EnumInt>2</EnumInt>
<PlainCh>2</PlainCh>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<wLevel>0</wLevel>
<uThumb>2</uThumb>
<uSurpInc>2</uSurpInc>
<uC99>2</uC99>
<uGnu>2</uGnu>
<useXO>2</useXO>
<v6Lang>0</v6Lang>
<v6LangP>0</v6LangP>
<vShortEn>2</vShortEn>
<vShortWch>2</vShortWch>
<v6Lto>2</v6Lto>
<v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti>
</Cads>
<Aads>
<interw>2</interw>
<Ropi>2</Ropi>
<Rwpi>2</Rwpi>
<thumb>2</thumb>
<SplitLS>2</SplitLS>
<SwStkChk>2</SwStkChk>
<NoWarn>2</NoWarn>
<uSurpInc>2</uSurpInc>
<useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt>
</Aads>
</FileArmAds>
</FileOption>
</File>
<File> <File>
<FileName>stm32f4xx_hal_spi.c</FileName> <FileName>stm32f4xx_hal_spi.c</FileName>
<FileType>1</FileType> <FileType>1</FileType>
@@ -1115,8 +1157,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1144,12 +1184,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1171,8 +1205,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1200,12 +1232,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1312,8 +1338,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -1341,12 +1365,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
<Aads> <Aads>
<interw>2</interw> <interw>2</interw>
@@ -1359,12 +1377,6 @@
<uSurpInc>2</uSurpInc> <uSurpInc>2</uSurpInc>
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
</GroupOption> </GroupOption>
@@ -1386,8 +1398,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1415,12 +1425,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1442,8 +1446,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1471,12 +1473,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1498,8 +1494,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1527,12 +1521,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1554,8 +1542,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1583,12 +1569,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1610,8 +1590,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1639,12 +1617,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1666,8 +1638,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1695,12 +1665,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1722,8 +1686,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1751,12 +1713,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1778,8 +1734,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1807,12 +1761,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1834,8 +1782,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1863,12 +1809,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1890,8 +1830,6 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument>
<IncludeLibraryModules></IncludeLibraryModules>
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<FileArmAds> <FileArmAds>
@@ -1919,12 +1857,6 @@
<v6Lto>2</v6Lto> <v6Lto>2</v6Lto>
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
<Undefine></Undefine>
<IncludePath></IncludePath>
</VariousControls>
</Cads> </Cads>
</FileArmAds> </FileArmAds>
</FileOption> </FileOption>
@@ -1946,8 +1878,8 @@
<AssembleAssemblyFile>2</AssembleAssemblyFile> <AssembleAssemblyFile>2</AssembleAssemblyFile>
<PublicsOnly>2</PublicsOnly> <PublicsOnly>2</PublicsOnly>
<StopOnExitCode>11</StopOnExitCode> <StopOnExitCode>11</StopOnExitCode>
<CustomArgument></CustomArgument> <CustomArgument />
<IncludeLibraryModules></IncludeLibraryModules> <IncludeLibraryModules />
<ComprImg>1</ComprImg> <ComprImg>1</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -1977,9 +1909,9 @@
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls>--diag_suppress=177</MiscControls> <MiscControls>--diag_suppress=177</MiscControls>
<Define></Define> <Define />
<Undefine></Undefine> <Undefine />
<IncludePath></IncludePath> <IncludePath />
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@@ -1994,10 +1926,10 @@
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>1</ClangAsOpt> <ClangAsOpt>1</ClangAsOpt>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls />
<Define></Define> <Define />
<Undefine></Undefine> <Undefine />
<IncludePath></IncludePath> <IncludePath />
</VariousControls> </VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
@@ -2085,8 +2017,8 @@
<AssembleAssemblyFile>0</AssembleAssemblyFile> <AssembleAssemblyFile>0</AssembleAssemblyFile>
<PublicsOnly>0</PublicsOnly> <PublicsOnly>0</PublicsOnly>
<StopOnExitCode>3</StopOnExitCode> <StopOnExitCode>3</StopOnExitCode>
<CustomArgument></CustomArgument> <CustomArgument />
<IncludeLibraryModules></IncludeLibraryModules> <IncludeLibraryModules />
<ComprImg>0</ComprImg> <ComprImg>0</ComprImg>
</CommonProperty> </CommonProperty>
<GroupArmAds> <GroupArmAds>
@@ -2115,10 +2047,10 @@
<v6WtE>2</v6WtE> <v6WtE>2</v6WtE>
<v6Rtti>2</v6Rtti> <v6Rtti>2</v6Rtti>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls />
<Define></Define> <Define />
<Undefine></Undefine> <Undefine />
<IncludePath></IncludePath> <IncludePath />
</VariousControls> </VariousControls>
</Cads> </Cads>
<Aads> <Aads>
@@ -2133,10 +2065,10 @@
<useXO>2</useXO> <useXO>2</useXO>
<ClangAsOpt>0</ClangAsOpt> <ClangAsOpt>0</ClangAsOpt>
<VariousControls> <VariousControls>
<MiscControls></MiscControls> <MiscControls />
<Define></Define> <Define />
<Undefine></Undefine> <Undefine />
<IncludePath></IncludePath> <IncludePath />
</VariousControls> </VariousControls>
</Aads> </Aads>
</GroupArmAds> </GroupArmAds>
@@ -3245,20 +3177,18 @@
</Groups> </Groups>
</Target> </Target>
</Targets> </Targets>
<RTE> <RTE>
<apis/> <apis />
<components> <components>
<component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.5.0" condition="ARMv6_7_8-M Device"> <component Cclass="CMSIS" Cgroup="CORE" Cvendor="ARM" Cversion="5.5.0" condition="ARMv6_7_8-M Device">
<package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.8.0"/> <package name="CMSIS" schemaVersion="1.3" url="http://www.keil.com/pack/" vendor="ARM" version="5.8.0" />
<targetInfos> <targetInfos>
<targetInfo name="STM32F407-Demo"/> <targetInfo name="STM32F407-Demo" />
</targetInfos> </targetInfos>
</component> </component>
</components> </components>
<files/> <files />
</RTE> </RTE>
<LayerInfo> <LayerInfo>
<Layers> <Layers>
<Layer> <Layer>
@@ -3267,5 +3197,4 @@
</Layer> </Layer>
</Layers> </Layers>
</LayerInfo> </LayerInfo>
</Project> </Project>
+23 -16
View File
@@ -73,28 +73,32 @@ FREERTOS.Events01=sys_evt,Dynamic,NULL
FREERTOS.FootprintOK=true FREERTOS.FootprintOK=true
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,FootprintOK,configTOTAL_HEAP_SIZE,Queues01,Events01 FREERTOS.IPParameters=Tasks01,configENABLE_FPU,FootprintOK,configTOTAL_HEAP_SIZE,Queues01,Events01
FREERTOS.Queues01=netMsgQueue,8,net_msg_t,0,Dynamic,NULL,NULL FREERTOS.Queues01=netMsgQueue,8,net_msg_t,0,Dynamic,NULL,NULL
FREERTOS.Tasks01=defaultTask,24,512,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;netTask,24,1024,StartNetTask,Default,NULL,Dynamic,NULL,NULL;ftpTask,24,1024,StartFtpTask,As weak,NULL,Dynamic,NULL,NULL;testTask,16,1024,start_test_task,As weak,NULL,Dynamic,NULL,NULL;uiTask,16,4096,StartUiTask,Default,NULL,Dynamic,NULL,NULL FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;netTask,24,1024,StartNetTask,Default,NULL,Dynamic,NULL,NULL;ftpTask,24,1024,StartFtpTask,As weak,NULL,Dynamic,NULL,NULL;testTask,16,2048,start_test_task,As weak,NULL,Dynamic,NULL,NULL;uiTask,16,4096,StartUiTask,Default,NULL,Dynamic,NULL,NULL
FREERTOS.configENABLE_FPU=1 FREERTOS.configENABLE_FPU=1
FREERTOS.configTOTAL_HEAP_SIZE=49152 FREERTOS.configTOTAL_HEAP_SIZE=49152
File.Version=6 File.Version=6
GPIO.groupedBy=Group By Peripherals GPIO.groupedBy=Group By Peripherals
IWDG.IPParameters=Prescaler,Reload
IWDG.Prescaler=IWDG_PRESCALER_64
IWDG.Reload=1249
KeepUserPlacement=false KeepUserPlacement=false
Mcu.CPN=STM32F407ZGT6 Mcu.CPN=STM32F407ZGT6
Mcu.Family=STM32F4 Mcu.Family=STM32F4
Mcu.IP0=DMA Mcu.IP0=DMA
Mcu.IP1=FREERTOS Mcu.IP1=FREERTOS
Mcu.IP10=USART1 Mcu.IP10=UART5
Mcu.IP11=USART2 Mcu.IP11=USART1
Mcu.IP12=USART3 Mcu.IP12=USART2
Mcu.IP13=USART3
Mcu.IP2=I2C1 Mcu.IP2=I2C1
Mcu.IP3=NVIC Mcu.IP3=IWDG
Mcu.IP4=RCC Mcu.IP4=NVIC
Mcu.IP5=SPI1 Mcu.IP5=RCC
Mcu.IP6=SPI2 Mcu.IP6=SPI1
Mcu.IP7=SYS Mcu.IP7=SPI2
Mcu.IP8=UART4 Mcu.IP8=SYS
Mcu.IP9=UART5 Mcu.IP9=UART4
Mcu.IPNb=13 Mcu.IPNb=14
Mcu.Name=STM32F407Z(E-G)Tx Mcu.Name=STM32F407Z(E-G)Tx
Mcu.Package=LQFP144 Mcu.Package=LQFP144
Mcu.Pin0=PE5 Mcu.Pin0=PE5
@@ -151,12 +155,13 @@ Mcu.Pin54=PB8
Mcu.Pin55=PE0 Mcu.Pin55=PE0
Mcu.Pin56=PE1 Mcu.Pin56=PE1
Mcu.Pin57=VP_FREERTOS_VS_CMSIS_V2 Mcu.Pin57=VP_FREERTOS_VS_CMSIS_V2
Mcu.Pin58=VP_SYS_VS_tim7 Mcu.Pin58=VP_IWDG_VS_IWDG
Mcu.Pin59=VP_SYS_VS_tim7
Mcu.Pin6=PB2 Mcu.Pin6=PB2
Mcu.Pin7=PF11 Mcu.Pin7=PF11
Mcu.Pin8=PF12 Mcu.Pin8=PF12
Mcu.Pin9=PG0 Mcu.Pin9=PG0
Mcu.PinsNb=59 Mcu.PinsNb=60
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32F407ZGTx Mcu.UserName=STM32F407ZGTx
@@ -484,7 +489,7 @@ PH1-OSC_OUT.Mode=HSE-External-Oscillator
PH1-OSC_OUT.Signal=RCC_OSC_OUT PH1-OSC_OUT.Signal=RCC_OSC_OUT
PinOutPanel.RotationAngle=0 PinOutPanel.RotationAngle=0
ProjectManager.AskForMigrate=true ProjectManager.AskForMigrate=true
ProjectManager.BackupPrevious=false ProjectManager.BackupPrevious=true
ProjectManager.CompilerLinker=GCC ProjectManager.CompilerLinker=GCC
ProjectManager.CompilerOptimize=6 ProjectManager.CompilerOptimize=6
ProjectManager.ComputerToolchain=false ProjectManager.ComputerToolchain=false
@@ -515,7 +520,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath= ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=false ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_I2C1_Init-I2C1-false-HAL-true,8-MX_UART4_Init-UART4-false-HAL-true,9-MX_UART5_Init-UART5-false-HAL-true,10-MX_USART2_UART_Init-USART2-false-HAL-true,11-MX_USART3_UART_Init-USART3-false-HAL-true ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_SPI1_Init-SPI1-false-HAL-true,7-MX_I2C1_Init-I2C1-false-HAL-true,8-MX_UART4_Init-UART4-false-HAL-true,9-MX_UART5_Init-UART5-false-HAL-true,10-MX_USART2_UART_Init-USART2-false-HAL-true,11-MX_USART3_UART_Init-USART3-false-HAL-true,12-MX_IWDG_Init-IWDG-false-HAL-true
RCC.48MHZClocksFreq_Value=84000000 RCC.48MHZClocksFreq_Value=84000000
RCC.AHBFreq_Value=168000000 RCC.AHBFreq_Value=168000000
RCC.APB1CLKDivider=RCC_HCLK_DIV4 RCC.APB1CLKDivider=RCC_HCLK_DIV4
@@ -575,6 +580,8 @@ USART3.IPParameters=VirtualMode
USART3.VirtualMode=VM_ASYNC USART3.VirtualMode=VM_ASYNC
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2 VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2 VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
VP_SYS_VS_tim7.Mode=TIM7 VP_SYS_VS_tim7.Mode=TIM7
VP_SYS_VS_tim7.Signal=SYS_VS_tim7 VP_SYS_VS_tim7.Signal=SYS_VS_tim7
board=custom board=custom
+69
View File
@@ -358,4 +358,73 @@ void vApplicationMallocFailedHook(void)
dbg_console_write_raw(msg, (unsigned)(sizeof(msg) - 1u)); dbg_console_write_raw(msg, (unsigned)(sizeof(msg) - 1u));
} }
/*
* 断言失败钩子(2026-09-29,配合 IWDG;见 Inc/FreeRTOSConfig.h 的 configASSERT)。
* 与栈溢出钩子同为"内核状态已不可信"路径:裸 UART 有界输出 + 主动复位,
* 不走 printf / 内核对象 / 控制台锁。
* 设计取舍(docs/子系统设计/看门狗设计说明.md §4.6):
* - 上报 file/line 是断言唯一有价值的现场信息,故必须打印(早于 TCB 名之类);
* - 打印后**主动 NVIC_SystemReset()** 而非空转:断言点未必能让 IWDG 抓到
* (若恰在启动段,IWDG 尚未启动),主动复位保证任何断言都能自恢复;
* 代价是 RCC_CSR 记 SFTRSTF 而非 IWDGRSTF——故上报串里写死 ASSERT 字样,
* 使"重启原因"可由日志区分(软件复位 + 上一条是 ASSERT = 断言导致)。
*/
void vApplicationAssertFailed(const char *file, long line)
{
static const char msg_head[] = "\r\n[ERR] ASSERT FAILED ";
const char *p = file;
char num[16];
int i;
/* 文件名只取末段(全路径太长且无信息量) */
if (p != NULL) {
const char *q = p;
while (*q != '\0') {
if ((*q == '/') || (*q == '\\')) {
p = q + 1;
}
q++;
}
/* 有界拷贝:上限 48 字符 */
{
uint16_t len = 0u;
char name[49];
while ((len < 48u) && (p[len] != '\0')) {
name[len] = p[len];
len++;
}
name[len] = '\0';
dbg_console_write_raw(msg_head, (unsigned)(sizeof(msg_head) - 1u));
dbg_console_write_raw(name, (unsigned)len);
}
} else {
dbg_console_write_raw(msg_head, (unsigned)(sizeof(msg_head) - 1u));
dbg_console_write_raw("(no file)", 9u);
}
dbg_console_write_raw(":", 1u);
/* 行号转十进制(不用 snprintf:钩子可能在临界区,且避免库依赖) */
i = 0;
if (line <= 0) {
num[i++] = '0';
} else {
char rev[16];
int n = 0;
while ((line > 0) && (n < 15)) {
rev[n++] = (char)('0' + (line % 10));
line /= 10;
}
while (n > 0) {
num[i++] = rev[--n];
}
}
dbg_console_write_raw(num, (unsigned)i);
dbg_console_write_raw(" (resetting)\r\n", 15u);
HAL_Delay(200); /* 等 UART 移位寄存器排空 */
NVIC_SystemReset();
}
/* USER CODE END Application */ /* USER CODE END Application */
+63
View File
@@ -0,0 +1,63 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file iwdg.c
* @brief This file provides code for the configuration
* of the IWDG instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "iwdg.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
IWDG_HandleTypeDef hiwdg;
/* IWDG init function */
void MX_IWDG_Init(void)
{
/* USER CODE BEGIN IWDG_Init 0 */
/* USER CODE END IWDG_Init 0 */
/* USER CODE BEGIN IWDG_Init 1 */
/* USER CODE END IWDG_Init 1 */
hiwdg.Instance = IWDG;
hiwdg.Init.Prescaler = IWDG_PRESCALER_64;
hiwdg.Init.Reload = 1249;
/* USER CODE BEGIN IWDG_DEFER_START */
/* ⚠ 生成区改动(唯一一处):原为 `HAL_IWDG_Init(&hiwdg)` 直呼。
* 原因:HAL_IWDG_Init() 内部第一句即 __HAL_IWDG_START()(立即启动看门狗,
* 之后不可停、只能复位)。而本函数被 CubeMX 插在 main() 的 MX_*_Init 序列里,
* 早于 app_main_init()——那段含 NAND 初始化/RTC/ADC,耗时可达数秒且无喂狗点,
* 按 2.5s 超时最坏值(≈1.7s)必然复位 → 开机死循环(2026-09-29 实测确认)。
* 故本函数降级为**只填参数不启动**;启动动作移交
* task_wd_start()(App/util/task_watchdog.c),由 defaultTask 在存储 bring-up
* 完成后调用——即"启动段不喂狗、主循环段才喂"的设计(见
* docs/子系统设计/看门狗设计说明.md §4.5)。
* 若 CubeMX 重生成覆盖此处,表现为"开机即复位",按本注释恢复即可。 */
/* USER CODE END IWDG_DEFER_START */
/* USER CODE BEGIN IWDG_Init 2 */
/* USER CODE END IWDG_Init 2 */
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
+15 -2
View File
@@ -21,6 +21,7 @@
#include "cmsis_os.h" #include "cmsis_os.h"
#include "dma.h" #include "dma.h"
#include "i2c.h" #include "i2c.h"
#include "iwdg.h"
#include "spi.h" #include "spi.h"
#include "usart.h" #include "usart.h"
#include "gpio.h" #include "gpio.h"
@@ -90,7 +91,17 @@ int main(void)
HAL_Init(); HAL_Init();
/* USER CODE BEGIN Init */ /* USER CODE BEGIN Init */
/* 复位原因锁存(2026-09-29,配合 IWDG):RCC_CSR 的复位标志只由上电复位(POR)
* 清除,其余复位(看门狗/软件/引脚/欠压)会跨复位保留——若不主动清除,
* 上一次的 IWDGRSTF 会一直挂着,导致每次启动都被误记为"看门狗复位"。
* 故在 HAL_Init()(此时 RCC 可用、串口尚未就绪)之后**立即读取并清除**,
* 锁存到 RCC_CSR 影子变量,待日志子系统起来后由 app_main_init 打印。
* 注意顺序:读 → 写 RMVF 清除,两步之间不可插入其它可能复位的代码。 */
{
extern volatile uint32_t g_rcc_csr_latched; /* 定义于 app_main.c,供启动日志读取 */
g_rcc_csr_latched = RCC->CSR; /* 锁存:含 IWDGRSTF/SFTRSTF/PORRSTF 等 */
RCC->CSR |= RCC_CSR_RMVF; /* 写 1 清全部复位标志(只清标志,不影响时钟) */
}
/* USER CODE END Init */ /* USER CODE END Init */
/* Configure the system clock */ /* Configure the system clock */
@@ -111,6 +122,7 @@ int main(void)
MX_UART5_Init(); MX_UART5_Init();
MX_USART2_UART_Init(); MX_USART2_UART_Init();
MX_USART3_UART_Init(); MX_USART3_UART_Init();
MX_IWDG_Init();
/* USER CODE BEGIN 2 */ /* USER CODE BEGIN 2 */
HAL_Delay(100); HAL_Delay(100);
@@ -155,8 +167,9 @@ void SystemClock_Config(void)
/** Initializes the RCC Oscillators according to the specified parameters /** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure. * in the RCC_OscInitTypeDef structure.
*/ */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 4; RCC_OscInitStruct.PLL.PLLM = 4;
+1 -1
View File
@@ -76,7 +76,7 @@ docs/
| [`系统墙钟时间维护说明.md`](子系统设计/系统墙钟时间维护说明.md) | `sys_clock`:RTC 基准、tick 回绕防护、30 天惰性再基准化 | | [`系统墙钟时间维护说明.md`](子系统设计/系统墙钟时间维护说明.md) | `sys_clock`:RTC 基准、tick 回绕防护、30 天惰性再基准化 |
| [`控制台单写者日志设计说明.md`](子系统设计/控制台单写者日志设计说明.md) | 控制台日志单写者模型(避免多任务交错输出) | | [`控制台单写者日志设计说明.md`](子系统设计/控制台单写者日志设计说明.md) | 控制台日志单写者模型(避免多任务交错输出) |
| [`运行与自检记录设计说明.md`](子系统设计/运行与自检记录设计说明.md) | `/log/run.log`·`selftest.log` 定长记录与待机显示 | | [`运行与自检记录设计说明.md`](子系统设计/运行与自检记录设计说明.md) | `/log/run.log`·`selftest.log` 定长记录与待机显示 |
| [`看门狗设计说明.md`](子系统设计/看门狗设计说明.md) | **调研+方案(待实施)**:IWDG 选型、任务心跳位图、复位原因分类、验证计划 | | [`看门狗设计说明.md`](子系统设计/看门狗设计说明.md) | **实施中**:IWDG(CubeMX 配置)+ 任务心跳位图;代码已落地编译通过,待台架故障注入/长跑验证 |
| [`网络/BSD_Socket_API_使用指南.md`](网络/BSD_Socket_API_使用指南.md) | **上层视图**:BSD Socket API 公开语义、示例、常见问题 | | [`网络/BSD_Socket_API_使用指南.md`](网络/BSD_Socket_API_使用指南.md) | **上层视图**:BSD Socket API 公开语义、示例、常见问题 |
| [`网络/BSD_Socket_API_函数调用关系.md`](网络/BSD_Socket_API_函数调用关系.md) | **内部视图**:netTask / 消息队列 / L3 挂起 / 重试对账的调用关系与设计意图 | | [`网络/BSD_Socket_API_函数调用关系.md`](网络/BSD_Socket_API_函数调用关系.md) | **内部视图**:netTask / 消息队列 / L3 挂起 / 重试对账的调用关系与设计意图 |
| [`网络/Net层阻塞模型架构设计.md`](网络/Net层阻塞模型架构设计.md) | **等待模型**:pending 请求架构、五路完成语义、设计边界与性能特征 | | [`网络/Net层阻塞模型架构设计.md`](网络/Net层阻塞模型架构设计.md) | **等待模型**:pending 请求架构、五路完成语义、设计边界与性能特征 |
@@ -36,10 +36,10 @@
<!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py --> <!-- MEM_SNAPSHOT:BEGIN generated by scripts/check_mem_numbers.py -->
| 区域 | 用量 | 容量 | 占比 | | 区域 | 用量 | 容量 | 占比 |
|---|---|---|---| |---|---|---|---|
| ER_IROM1 | 261,932 B (255.79 KB) | 1,048,576 B (1024 KB) | 25.0% | | ER_IROM1 | 264,860 B (258.65 KB) | 1,048,576 B (1024 KB) | 25.3% |
| RW_IRAM1 | 87,040 B (85.00 KB) | 131,072 B (128 KB) | 66.4% | | RW_IRAM1 | 87,080 B (85.04 KB) | 131,072 B (128 KB) | 66.4% |
| RW_CCM | 49,184 B (48.03 KB) | 65,536 B (64 KB) | 75.0% | | RW_CCM | 49,184 B (48.03 KB) | 65,536 B (64 KB) | 75.0% |
| **Flash (ROM 合计)** | **262,660 B (256.5 KB)** | 1,048,576 B (1024 KB) | **25.0%** | | **Flash (ROM 合计)** | **265,616 B (259.4 KB)** | 1,048,576 B (1024 KB) | **25.3%** |
<!-- MEM_SNAPSHOT:END --> <!-- MEM_SNAPSHOT:END -->
各区的容量与常量来源: 各区的容量与常量来源:
+132 -60
View File
@@ -1,9 +1,10 @@
# 看门狗设计说明 # 看门狗设计说明
> **模块名称**:独立看门狗(IWDG)+ 任务心跳位图 > **模块名称**:独立看门狗(IWDG)+ 任务心跳位图
> **文档定位**:**调研 + 设计方案**——记录选型依据、在既有平台上落地的约束、 > **文档定位**:**实施中**——记录选型依据、在既有平台上落地的约束、实现现状与
> 推荐架构与分步实施路径。**尚未实施**,实施后本文件应改写为"现状设计说明"。 > 待台架验证项。**代码骨架已落地并编译通过**(§10 第 0~6 步);第 7~10 步
> **状态**:📋 设计完成,待实施(登记于 [`../待处理内容.md`](../待处理内容.md) N-03) > (故障注入 / 长跑 / 本文档转为"现状设计说明")待台架。
> **状态**:🚧 代码已落地(`@build` 0/0),**待台架故障注入与长跑验证**;登记于 [`../待处理内容.md`](../待处理内容.md) N-03
> **日期**:2026-09-29 > **日期**:2026-09-29
> **相关文档**: > **相关文档**:
> [`../审查记录/项目审查与优化建议报告.md`](../审查记录/项目审查与优化建议报告.md)(N-03 缺陷原始登记)、 > [`../审查记录/项目审查与优化建议报告.md`](../审查记录/项目审查与优化建议报告.md)(N-03 缺陷原始登记)、
@@ -33,8 +34,7 @@
> ⚠️ **实施路径因此改变**:`HAL_IWDG_MODULE_ENABLED` 不是一个"取消注释即可"的开关—— > ⚠️ **实施路径因此改变**:`HAL_IWDG_MODULE_ENABLED` 不是一个"取消注释即可"的开关——
> 取消后 `stm32f4xx_hal_conf.h` 会去 include 一个**不存在的头文件**,直接编译失败。 > 取消后 `stm32f4xx_hal_conf.h` 会去 include 一个**不存在的头文件**,直接编译失败。
> 本方案因此**不走 HAL 驱动,改用直接寄存器操作**(见 §2.2)——这反而是更优路径, > 故须**由 CubeMX 勾选 IWDG 后重生成**,让驱动源码与 HUD 开关一并就位(见 §2.2)。
> 因为 CMSIS 设备头**已提供完整的 IWDG 寄存器定义与实例指针**,零新增依赖。
### 1.2 现存的两处"假保护" ### 1.2 现存的两处"假保护"
@@ -108,7 +108,14 @@ T_IWDG = (4 × 2^PR) × RLR / F_LSI
**本方案选定(见 §4.3)**:`PR=4`(64 分频)/ `RLR=1249` → 标称 **2498 ms**、 **本方案选定(见 §4.3)**:`PR=4`(64 分频)/ `RLR=1249` → 标称 **2498 ms**、
最坏 **≈1701 ms**。 最坏 **≈1701 ms**。
### 2.2 实施路径:直接寄存器操作,不引入 HAL IWDG 驱动 ### 2.2 实施路径:**走 CubeMX 生成**(原方案为直接寄存器,已变更)
> **变更说明(2026-09-29)**:本节初稿推荐"直接寄存器操作"(下称路径 C),依据是
> HAL IWDG 驱动源码不在仓库。经与项目负责人确认,**改走 CubeMX 图形界面生成**
> (路径 A)——让 `.ioc` 成为配置的唯一事实源、与其他外设保持一致。路径 A 的
> 原评估"高风险"已被本次实践证伪:重生成带来的定制覆盖是**有限且可枚举**的
> (实测见 §10 第 2 步),处理方式已固化为"重生成 → 逐项恢复 → 编译验证"。
> 以下保留路径比较,作为决策记录。
**约束事实**(§1.1 表的第 3、4 行):HAL IWDG 驱动源码**不在仓库**、也**不在 MDK 工程**中。 **约束事实**(§1.1 表的第 3、4 行):HAL IWDG 驱动源码**不在仓库**、也**不在 MDK 工程**中。
CubeMX 只在勾选该外设时才会把 `stm32f4xx_hal_iwdg.c/h` 拷进 `Drivers/STM32F4xx_HAL_Driver/`。 CubeMX 只在勾选该外设时才会把 `stm32f4xx_hal_iwdg.c/h` 拷进 `Drivers/STM32F4xx_HAL_Driver/`。
@@ -120,16 +127,44 @@ CubeMX 只在勾选该外设时才会把 `stm32f4xx_hal_iwdg.c/h` 拷进 `Driver
| 路径 | 做法 | 评估 | | 路径 | 做法 | 评估 |
|---|---|---| |---|---|---|
| A. 从 CubeMX 重新生成(勾选 IWDG) | 用 `.ioc` 勾选 IWDG 后生成 | ❌ **高风险**:CubeMX 重生成会重写 `Src/`/`Inc/` 生成区,项目有大量既存定制(见 `AGENTS.md`「平台约束」),且会带回行尾空白抖动(2026-09-20 已记录过该问题) | | **A. 从 CubeMX 重新生成(勾选 IWDG)**(**实际采用**) | 用 `.ioc` 勾选 IWDG 后生成 | ✅ **配置单一事实源、与其他外设一致**;代价 = 需恢复被覆盖的既有定制(实测 4 处,见 §10 第 2 步),且须按 `AGENTS.md` 处理行尾空白抖动 |
| B. 手工补入 `stm32f4xx_hal_iwdg.c/h` | 从 STM32CubeF4 包拷贝两文件 + 注册进 MDK 工程 | ⚠️ 可行但需**手改 `.uvprojx`**(XML 结构脆弱),且引入约 0.3 KB Flash 的 HAL 封装 | | B. 手工补入 `stm32f4xx_hal_iwdg.c/h` | 从 STM32CubeF4 包拷贝两文件 + 注册进 MDK 工程 | ⚠️ 需**手改 `.uvprojx`**(XML 结构脆弱),且引入约 0.3 KB Flash 的 HAL 封装;`.ioc` 与代码脱节 |
| **C. 直接寄存器操作**(**本方案选定**) | 用 CMSIS 已提供的 `IWDG` 实例指针 + 寄存器位域宏 | ✅ **零新增依赖、零工程文件改动、代码量约 20 行** | | C. 直接寄存器操作(初稿推荐,**已放弃**) | 用 CMSIS 已提供的 `IWDG` 实例指针 + 寄存器位域宏 | ✅ 零新增依赖、零工程文件改动、约 20 行;❌ 但**破坏了"外设配置统一由 CubeMX 表达"的约定**,后续维护者无处可查"这台设备的 IWDG 配了什么" |
**选 C 的依据**:CMSIS 设备头 `Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f407xx.h` **选 A 的依据**:本项目的既有约定是"外设配置 = `.ioc`"(`AGENTS.md`「平台约束」:
**已完整提供**所需的一切(已实测确认): `Inc/`/`Src/` 中 CubeMX 生成文件带 `USER CODE` 标记,自定义代码只写标记区内)。
IWDG 若用裸寄存器,则分频/重载值只散落在 `App/util/task_watchdog.c` 的宏里,
与 `.ioc` 无关联——下一个维护者改超时值时**不会想到去改代码宏**。
路径 A 让该配置出现在 CubeMX 界面里,符合项目惯例。
**CubeMX 侧配置值**(在 `.ioc` / CubeMX 图形界面填写):
| 项 | 值 | 说明 |
|---|---|---|
| Activated | ✅ 勾选 | Peripheral 树 → IWDG |
| IWDG counter clock prescaler | **64** | 对应 `IWDG_PRESCALER_64`,即 `PR=4` |
| IWDG down-counter reload value | **1249** | 12 位,范围 0~4095 |
| Window value | —— | ⚠️ **本 HAL 版本 `IWDG_InitTypeDef` 无此字段**(仅 `Prescaler` / `Reload`),CubeMX 界面亦无该项;窗口寄存器保持复位默认 `0xFFF` = 禁用窗口,符合预期 |
生成结果:`Src/iwdg.c` / `Inc/iwdg.h`(新文件)、`Drivers/STM32F4xx_HAL_Driver/{Inc,Src}/stm32f4xx_hal_iwdg.{h,c}`、
`Inc/stm32f4xx_hal_conf.h` 中 `HAL_IWDG_MODULE_ENABLED` 解除注释、`.uvprojx` 挂载驱动、
`Src/main.c` 的 `MX_*_Init()` 序列新增 `MX_IWDG_Init()`。
> ⚠️ **路径 A 的固有陷阱(本次实测踩中,P0)**:CubeMX 把 `MX_IWDG_Init()` 插在
> `app_main_init()` **之前**,而 `HAL_IWDG_Init()` 内部第一句即
> `__HAL_IWDG_START(hiwdg)`(立即启动、之后不可停)。启动段(NAND 初始化等)耗时
> 可达数秒且无喂狗点 → 按 2.5s 超时必然复位 → **开机死循环**。
> **CubeMX 界面无法关闭这个自动启动**(HAL 行为,无对应选项)。
> 解决办法见 §4.5 决策 C:把 `Src/iwdg.c` 里那一行 `HAL_IWDG_Init(&hiwdg)` 换成
> 只填参数的 USER CODE 注释块,启动动作移交 `task_wd_start()`。
> 这是路径 A 下**唯一必须手工修改生成文件**的地方,已在文件内留注释说明恢复方法。
**参考:CMSIS 设备头已提供的寄存器定义**(路径 C 曾依赖,现仅作 `task_wd_beat`/`task_wd_poll`
里裸写 `IWDG->KR` 的依据):
| 已有定义 | 位置 | 内容 | | 已有定义 | 位置 | 内容 |
|---|---|---| |---|---|---|
| `IWDG_TypeDef` | `:573-579` | `KR` / `PR` / `RLR` / `SR` 四寄存器结构体 | | `IWDG_TypeDef` | `stm32f407xx.h:573-579` | `KR` / `PR` / `RLR` / `SR` 四寄存器结构体 |
| `IWDG_BASE` | `:944` | `APB1PERIPH_BASE + 0x3000` | | `IWDG_BASE` | `:944` | `APB1PERIPH_BASE + 0x3000` |
| `IWDG` 实例指针 | `:1068` | `((IWDG_TypeDef *) IWDG_BASE)` | | `IWDG` 实例指针 | `:1068` | `((IWDG_TypeDef *) IWDG_BASE)` |
| `IWDG_KR_KEY_Msk` | `:9331` | 键值字段掩码 | | `IWDG_KR_KEY_Msk` | `:9331` | 键值字段掩码 |
@@ -137,7 +172,7 @@ CubeMX 只在勾选该外设时才会把 `stm32f4xx_hal_iwdg.c/h` 拷进 `Driver
| `IWDG_RLR_RL_Msk` | `:9344` | 重装值字段(12 位) | | `IWDG_RLR_RL_Msk` | `:9344` | 重装值字段(12 位) |
| `IWDG_SR_PVU` / `IWDG_SR_RVU` | `:9349-9353` | 更新进行中标志(须轮询等它清零) | | `IWDG_SR_PVU` / `IWDG_SR_RVU` | `:9349-9353` | 更新进行中标志(须轮询等它清零) |
**键值常量**(上游 HAL 在 `stm32f4xx_hal_iwdg.h` 定义,本方案需自行定义): **键值常量**(由 HAL 定义在 `stm32f4xx_hal_iwdg.h`,本方案在 `task_watchdog.c` 内裸写):
| 用途 | 值 | | 用途 | 值 |
|---|---| |---|---|
@@ -149,9 +184,10 @@ CubeMX 只在勾选该外设时才会把 `stm32f4xx_hal_iwdg.c/h` 拷进 `Driver
IWDG 是**"写键值"式外设**:写 `0x5555` 解锁 → 配 `PR`/`RLR` → 写 `0xCCCC` 启动 IWDG 是**"写键值"式外设**:写 `0x5555` 解锁 → 配 `PR`/`RLR` → 写 `0xCCCC` 启动
(启动后**不可停**,只能复位)→ 此后周期性写 `0xAAAA` 喂狗。 (启动后**不可停**,只能复位)→ 此后周期性写 `0xAAAA` 喂狗。
> **为何这会被称为"更优路径"**:HAL 的 `HAL_IWDG_Init()` 内部做的事就是上面这几步, > **喂狗为何仍走裸寄存器而非 `HAL_IWDG_Refresh()`**:喂狗是 100 ms 级高频操作,
> 外加一个 `IWDG_HandleTypeDef` 状态机。本项目不需要那层封装——寄存器操作总共 > HAL 封装带 `IWDG_HandleTypeDef` 有效性检查(读 `State` 字段、判 `LOCKED`),
> 约 20 行,且完全落在 `App/util/task_watchdog.c` 内,**不触碰任何 CubeMX 生成文件**。 > 在高频路径上无收益。`Task_wd_poll()` 里写 `IWDG->KR = 0xAAAA` 是 1 条存储指令。
> 这不是"绕过 HAL",而是"HAL 提供了该寄存器定义,直接用"——与路径选择无关。
--- ---
@@ -558,22 +594,24 @@ void task_wd_poll(void)
> 丢失"是看门狗抓到的"这一关键信息。**让 IWDG 自然溢出**, > 丢失"是看门狗抓到的"这一关键信息。**让 IWDG 自然溢出**,
> 复位原因才是权威的 `watchdog reset`。代价是额外的 ≤2.5 s 延迟(可接受)。 > 复位原因才是权威的 `watchdog reset`。代价是额外的 ≤2.5 s 延迟(可接受)。
### 5.4 各任务的埋点位置 ### 5.4 各任务的埋点位置(**2026-09-29 已全部落地**)
| 任务 | 埋点位置 | 备注 | | 任务 | 实际埋点位置 | 备注 |
|---|---|---| |---|---|---|
| `defaultTask` | `default_task_func` 的 `for(;;)` 循环首行 | 50 ms 节拍,天然满足 | | `defaultTask` | `App/task/default_task.c`:`for(;;)` 首行 `task_wd_poll()` + `task_wd_beat(TASK_WD_DEFAULT)` | 50 ms 节拍,天然满足;同时是唯一喂狗者 |
| `netTask` | 主循环 `for(;;)` 内(`net_poll` 之后) | 1 ms 节拍;另需在 `net_stack_bring_up` 的 PHY 等待循环内补埋点(§4.4) | | `netTask` | `App/task/net_task.c`:① 主循环 `for(;;)` 首行;② `net_stack_bring_up` 的 PHY 等待循环内 `osDelay(50)` 前;③ `ENABLE_HW_LAYER_TESTS` 自挂起分支(掩码已剔除,埋点无副作用) | ② 为 §4.4 白名单项:PHY 最长等待 3 s(60×50 ms),必须在其中补心跳 |
| `ftpTask` | ⚠️ 见 §4.3 —— 第一步**剔除掩码**;后续改 `Lib/lftpd` 时再补 | 已知缺口 | | `ftpTask` | ⚠️ **首期不埋点**——由 `wd_required_mask()` **剔除**(见 §4.3) | 已知缺口:`Lib/lftpd` 事件循环改动面大,二期再补 |
| `uiTask` | `ui_task_func` 主循环(`osDelay(10)` 处) | 10 ms 节拍 | | `uiTask` | `App/task/ui_task.c`:`ui_port_step(10)` / `ui_net_sink_poll()` 之后 | 10 ms 节拍;等待 NET_READY 期间不喂属**预期**(该段卡死即应复位) |
| `timeSyncTask` | `time_sync_task` 主循环 | 最长 `vTaskDelay(2000)`——⚠️ **2 s > 800 ms 容忍窗口**,需拆分:在 `vTaskDelay` 前多次分段置位,或把该 timeout 缩短 | | `timeSyncTask` | `App/sync/time_sync.c`:① `time_sync_task` 主循环首行;② 监听重试的 500 ms / 2 s 延时前;③ accept 轮询 200 ms 延时前;④ 收尾 50 ms 延时前;⑤ **`time_sync_handle_conn` 内的等待循环**(关键:把 30 s 总预算切成 `TIME_SYNC_WAIT_SLICE_MS`=200 ms 的片,每片先喂心跳) | ⑤ 是本案最要害的一处:对端连上但不发时间包是完全正常的场景,若不切片,30 s 等待必然被判卡死 |
| `testTask` | 由套件掩码决定 | 套件运行时可长阻塞,按 §4.1 排除 | | `testTask` | 不埋点——由套件掩码决定,按 §4.1 排除 | 套件运行时可长阻塞 |
> ⚠️ **`timeSyncTask` 是关键风险点**:其主循环有两处 `vTaskDelay(pdMS_TO_TICKS(2000))` > ⚠️ **实施时的新发现(补充 §4.4 白名单)**:`timeSyncTask` 的风险**不止**
> (`App/sync/time_sync.c:68/75`)。若心跳位只在循环首行,则 2 s 内位图恒缺席, > 主循环里那两处 `vTaskDelay(2000)`——`time_sync_handle_conn` 内部的
> **必然触发停喂**。处理三选一:① 每 200 ms 分段置位;② 缩短该 delay; > `net_recv_to(..., rem)` 单次可睡满 **30 s 总预算**。初稿只注意到 `vTaskDelay`
> ③ 该任务单独用"宽松窗口"(增大容忍次数到 25 次 = 2.5 s,但会逼近 IWDG 超时,不推荐)。 > 的两处,会漏掉这处。处理方式取"**切片**"而非"放宽窗口":
> **推荐 ①**:把 2 s 拆成 10 × 200 ms 循环,每次置位并检查退出条件——语义不变,且提升响应性。 > 新增 `TIME_SYNC_WAIT_SLICE_MS = 200U`,把单次等待的 `rem` 夹到 ≤200 ms,
> 每片先 `task_wd_beat()`。总预算语义(≤30 s)完全不变,只是把一次长睡眠
> 拆成多次短睡眠——同时提升了"对端提前到达"的响应粒度。
--- ---
@@ -581,26 +619,41 @@ void task_wd_poll(void)
### 6.1 串口标记(供 `@test` 采集) ### 6.1 串口标记(供 `@test` 采集)
**实际实现**(2026-09-29 落地,`App/app/app_main.c` + `App/util/task_watchdog.c` +
`Src/freertos.c`):
| 标记 | 时机 | 含义 | | 标记 | 时机 | 含义 |
|---|---|---| |---|---|---|
| `[WD] reset cause=<类型>` | `app_main_init` 早期 | 复位原因(`power on` / `watchdog reset` / `soft reset` / `pin reset`) | | `[APP] reset cause: <类型> (CSR=0x%08X)` | `app_main_init` 早期 | 复位原因,类型为 `IWDG (independent watchdog)` / `WWDG (window watchdog)` / `software (NVIC_SystemReset)` / `power-on (POR)` / `external pin (NRST)` / `brown-out (BOR)` / `unknown`;同时打印 `RCC_CSR` 原值便于事后核对 |
| `[WD] watchdog armed (timeout=2500ms)` | `task_wd_start()` | IWDG 已启动(真机自检必查标记) | | `[WD] armed: timeout ~2498ms (worst ~1701ms), miss_tol=800ms` | `task_wd_start()` | IWDG 已启动(真机自检必查标记) |
| `[WD] miss streak=<n> mask=0x%08X` | 每次未达标(限流打印) | 谁没动(`mask` 中 0 位 = 缺失任务) | | `[WD] task stall: mask=0x%08X req=0x%08X miss=%lu` | 连续 8 窗未达标时(每窗一次,共打印至复位) | 即将停喂 → 约 2.5 s 后 IWDG 复位。`mask` 的 0 位 = 缺席任务 |
| `[ERR] WATCHDOG: task stall` | 停喂时 | 即将复位,最后遗言 | | `[ERR] ASSERT FAILED <file>:<line> (resetting)` | `vApplicationAssertFailed()` | FreeRTOS 断言失败(`Src/freertos.c`),打印后主动复位 |
| `[WD] beat ok` | 可选,调试期 | 心跳正常(默认关闭,避免刷屏) | | `[ERR] STACK OVERFLOW task=<name>` | `vApplicationStackOverflowHook` | 既有钩子(栈溢出) |
| `[ERR] MALLOC FAILED (heap exhausted)` | `vApplicationMallocFailedHook` | 既有钩子(堆耗尽,只告警不复位) |
> 日志标签说明:`[APP]` 是 `App/app/app_main.c` 的 `DBG_TAG`;`[WD]` 是
> `App/util/task_watchdog.c` 的 `DBG_TAG`(定义在两个 include 之间,
> 是 `dbg_log.h` 的既有取标签方式)。全部为纯 ASCII,规避 `AGENTS.md` 记载的
> ARMCC CP936 字符串字面量陷阱。
### 6.2 与 `run.log` 的集成 ### 6.2 与 `run.log` 的集成
`sys_log_mcu.c` 的 `syslog_mcu_mounted()` 当前只写 `power on` / `reboot` `sys_log_mcu.c` 的 `syslog_mcu_mounted()` 当前只写 `power on` / `reboot`
(靠 `run.log` 末条 epoch 时间差推断)。**改为优先用硬件标志**: (靠 `run.log` 末条 epoch 时间差推断)。**现状:未改**——本次实施选择
"先只在串口上报 `reset cause`",理由:
1. 串口标记已经能支撑 `@test` 判定与人工归因,`run.log` 的价值在于**长期累计**;
2. 写 `run.log` 涉及 UI 字符集("看门狗"三字是否在位)与既有 600 s 时间窗分类逻辑,
改动面比串口上报大,**留作二期**(`待处理内容.md` N-03 后续项)。
**二期计划**(复位原因映射表,优先级见 §4.8):
``` ```
复位原因(§4.8 优先级)→ 描述串映射: power-on (POR) → "power on" (既有)
power on → "power on" (既有) IWDG / WWDG → "watchdog" (新增,UI 字符集需补"看门狗"三字)
watchdog reset → "watchdog" (新增,UI 字符集需补"看门狗"三字) software → "soft reset" (新增)
soft reset → "soft reset" (新增) external pin → "pin reset" (新增)
pin reset → "pin reset" (新增) 其余 → 回退既有 600s 时间窗分类
其余 → 回退既有 600s 时间窗分类
``` ```
> ⚠️ **UI 字符集影响**:`docs/子系统设计/运行与自检记录设计说明.md` §6.1 记录了 > ⚠️ **UI 字符集影响**:`docs/子系统设计/运行与自检记录设计说明.md` §6.1 记录了
@@ -685,24 +738,42 @@ void task_wd_poll(void)
## 10. 实施步骤(按序执行,每步端到端验证) ## 10. 实施步骤(按序执行,每步端到端验证)
| 步 | 内容 | 验证 | | 步 | 内容 | 验证 | 状态 |
|---|---|---| |---|---|---|---|
| **1** | 新建 `App/util/task_watchdog.c/h`;实现 IWDG 寄存器级 `wd_iwdg_init/feed` + 心跳位图;**登记进 MDK 工程** | `@build` 0/0 | | **0** | **(新增)** CubeMX 勾选 IWDG(Prescaler=64 / Reload=1249)→ 重生成 → **恢复被覆盖的定制** | `@build` 0/0 + 启动日志齐全 | ✅ **2026-09-29 完成**,覆盖 4 处见下 |
| **2** | `Src/main.c` 复位原因锁存 + 清标志;`syslog_mcu.c` 写描述串 | V7/V8(`cause` 正确) | | **1** | 新建 `App/util/task_watchdog.c/h`;实现心跳位图 + 抽样判定 + IWDG 延后启动;**登记进 MDK 工程**(`App` 组,`sys_clock.c` 之后) | `@build` 0/0 | ✅ 完成 |
| **3** | 实现抽样判定 + 串口标记(**暂不启动 IWDG**) | V1 观察 `[WD] beat ok`(调试期) | | **2** | `Src/main.c` 复位原因锁存 + 清标志;`App/app/app_main.c` 打印描述串 | `[APP] reset cause:` 出现 | ✅ 完成(`run.log` 写入留二期) |
| **4** | 各任务埋点(含 `timeSyncTask` 拆分) | V5 短跑(5 min)无 `miss` 打印 | | **3** | `Src/iwdg.c` 阻止 `HAL_IWDG_Init()` 自动启动(P0) | 开机不死循环 | ✅ 完成 |
| **5** | `task_wd_start()` 启动 IWDG(写 `0xCCCC`) | V1 + V5 | | **4** | 各任务埋点(含 `timeSyncTask` **切片**而非拆 delay) | 编译 0/0;串口无 `miss` | ✅ 完成 |
| **6** | `configASSERT` 改造 + `vApplicationAssertFailed()` | V3 | | **5** | `task_wd_start()` 由 `defaultTask` 在 bring-up 完成后调用 | `[WD] armed:` 出现 | ✅ 完成 |
| **7** | 故障注入(V2/V4) | 复位 + `cause` 正确 | | **6** | `configASSERT` 改造 + `vApplicationAssertFailed()` | 编译 0/0 | ✅ 完成 |
| **8** | 模拟器 `--watchdogtest` + stub | S1 | | **7** | 故障注入(V2/V4):人为制造任务卡死 | 复位 + `reset cause: IWDG` | ⏳ **待台架** |
| **9** | 长跑(V5,≥30 min,真实负载) | **零复位** | | **8** | 模拟器 `--watchdogtest` + stub | S1 | ⏳ 待做 |
| **10** | 本文档改写为"现状设计说明";`待处理内容.md` N-03 销项;`README.md` 登记 | 门禁 | | **9** | 长跑(V5,≥30 min,真实负载) | **零复位** | ⏳ **待台架** |
| **10** | 本文档改写为"现状设计说明";`待处理内容.md` N-03 销项;`README.md` 登记 | 门禁 | ⏳ 待第 7~9 步结论 |
> **每步改完必须 `@build` 0 错误 0 警告**(`AGENTS.md` 铁律)。 ### 10.1 第 0 步实测:CubeMX 重生成覆盖了哪 4 处
>
> **第 1 步的风险点**:`App/util/task_watchdog.c` 需在 `MDK-ARM/*.uvprojx` 中挂载。 `.ioc` 的 `ProjectManager.DeletePrevious=true` + `KeepUserCode=true` 决定了
> 若挂载不顺,可临时把实现放进 `App/task/default_task.c`(已在工程内)验证逻辑, **只有 `USER CODE BEGIN/END` 标记区内的代码受保护**。实测被覆盖的定制:
> 待工程文件可改时再抽成独立模块。**两种形态的逻辑完全一致**。
| 级别 | 文件 | 被覆盖内容 | 恢复方式 |
|---|---|---|---|
| **P0** | `Src/iwdg.c`(新文件) | CubeMX 生成的 `MX_IWDG_Init()` 直接调 `HAL_IWDG_Init()` → 开机死循环 | 改为只填参数;插 `USER CODE BEGIN IWDG_DEFER_START` 注释块说明(**唯一必需的手工改动**) |
| **P1** | `Src/stm32f4xx_it.c` | `HardFault_Handler` 崩溃现场采集(91 行:PC/LR/xPSR/R0-R3/CFSR/HFSR/BFAR/MMFAR)被打回空 `while(1)` | 整块换回手工版(`__asm void` 汇编取 MSP/PSP + `hard_fault_report`) |
| **P1** | `Inc/FreeRTOSConfig.h` | `configCHECK_FOR_STACK_OVERFLOW 2` + `configUSE_MALLOC_FAILED_HOOK 1` **整个块被删除** | 插回 `USER CODE BEGIN FREE_RTOS_CONFIG_HARDENING` 块 |
| **P2** | `Src/freertos.c` | 三处中文注释丢失(任务栈大小的实测记录) | 恢复注释(栈**数值**未丢,`.ioc` 同步到位) |
> ⚠️ **P1 两处的教训**:它们都在 `USER CODE` 标记区**之外**(`stm32f4xx_it.c` 的
> `HardFault_Handler` 由 CubeMX 直接生成;`FreeRTOSConfig.h` 的加固宏原本写在
> 非 `USER CODE` 区)。**P1 的丢失不会立刻暴露**——栈溢出检测与堆失败钩子只在
> 真发生溢出/耗尽时才起作用,且 `HardFault_Handler` 被打回空死循环后
> **崩溃时连现场都打不出来**(只剩 IWDG 兜底复位,但归因信息全丢)。
> 故本次已把这三个宏搬进 `USER CODE BEGIN 1` 区,并加注释
> "⚠ 本段为手工添加,CubeMX 重生成会删除(2026-09-29 实测),改完须核对本块存在"。
> **每步改完必须 `@build` 0 错误 0 警告**(`AGENTS.md` 铁律)。第 0~6 步已一次性
> 验证通过:`BUILD_OK: 0 errors, 0 warnings`。
--- ---
@@ -711,7 +782,7 @@ void task_wd_poll(void)
| 议题 | 结论 | | 议题 | 结论 |
|---|---| |---|---|
| **选型** | **IWDG**(独立 LSI),非 WWDG(依赖 APB1 + 中断,在关中断/HardFault 场景失效) | | **选型** | **IWDG**(独立 LSI),非 WWDG(依赖 APB1 + 中断,在关中断/HardFault 场景失效) |
| **实施路径** | **直接寄存器操作**(不引入 HAL IWDG 驱动)——驱动源码不在仓库、也未经由 CubeMX 生成,CMSIS 设备头已提供全部寄存器定义(§2.2) | | **实施路径** | **CubeMX 勾选 IWDG 生成**(`.ioc` = 配置单一事实源,与其他外设一致);唯一手工改动 = `Src/iwdg.c` 中阻止 `HAL_IWDG_Init()` 立即启动(§2.2 / §4.5) |
| **架构** | **任务心跳位图(各自置位,无锁单字)+ defaultTask 单一喂狗者**——避免"有人跑就喂狗"的假保护 | | **架构** | **任务心跳位图(各自置位,无锁单字)+ defaultTask 单一喂狗者**——避免"有人跑就喂狗"的假保护 |
| **超时** | 2498 ms(PR=4 / RLR=1249);最坏(LSI 47 kHz)≈1701 ms;中间留 800 ms 停喂判定裕度 | | **超时** | 2498 ms(PR=4 / RLR=1249);最坏(LSI 47 kHz)≈1701 ms;中间留 800 ms 停喂判定裕度 |
| **启动时机** | **defaultTask bring-up 完成后**——绕开初始化深链超时陷阱,代价是启动段无保护 | | **启动时机** | **defaultTask bring-up 完成后**——绕开初始化深链超时陷阱,代价是启动段无保护 |
@@ -768,4 +839,5 @@ void task_wd_poll(void)
| 日期 | 变更 | 说明 | | 日期 | 变更 | 说明 |
|---|---|---| |---|---|---|
| 2026-09-29 | 创建 | 调研 + 设计方案:IWDG + 任务心跳位图;含选型、九项设计决策、验证计划与风险清单 | | 2026-09-29 | 创建 | 调研 + 设计方案:IWDG + 任务心跳位图;含选型、九项设计决策、验证计划与风险清单 |
| 2026-09-29 | 修正实施路径 | 实测发现 HAL IWDG 驱动源码不在仓库且未编入 MDK 工程 → 改为**直接寄存器操作**(§2.2 路径 C);超时数值按公式核算修正;补 `RCC_CSR`/`IWDG` 寄存器定义的实测行号 | | 2026-09-29 | 修正实施路径 | 实测发现 HAL IWDG 驱动源码不在仓库且未编入 MDK 工程 → 初稿改为**直接寄存器操作**(§2.2 路径 C);超时数值按公式核算修正;补 `RCC_CSR`/`IWDG` 寄存器定义的实测行号 |
| 2026-09-29 | **路径再变更 + 实施落地** | 决策改走 **CubeMX 图形配置**(§2.2 路径 A):`HAL_IWDG_MODULE_ENABLED` 改为经 CubeMX 生成(避免"取消注释即编译失败")。同时落地 §5 骨架到 `App/util/task_watchdog.{c,h}`,各任务埋点(default/net/ui/time_sync),`RCC_CSR` 复位原因锁存(`Src/main.c` + `App/app/app_main.c`),`configASSERT` 改为 `vApplicationAssertFailed()`。实测 CubeMX 重生成覆盖 4 处既有定制(P0×1 + P1×2 + P2×1),已全部恢复,`@build` 0 错误 0 警告 |
+4 -3
View File
@@ -30,6 +30,7 @@
| # | 事项 | 说明 | 出处 | | # | 事项 | 说明 | 出处 |
|---|---|---|---| |---|---|---|---|
| N-03 | **引入独立看门狗(IWDG)+ 任务心跳位图**——现状全库无看门狗(HAL 驱动源码也不在仓库),任何形态死机不可自恢复;另 `configASSERT` 为关中断死循环(连日志都不打)。**设计方案已完成**(含选型、九项决策、验证计划、风险清单),待实施 | **设计见 [`子系统设计/看门狗设计说明.md`](子系统设计/看门狗设计说明.md)**;实施路径为直接寄存器操作(不引入 HAL IWDG 驱动);实施后本文档改写为现状设计说明并销项 | `审查记录/项目审查与优化建议报告.md` N-03a/b/c | | N-03 | **引入独立看门狗(IWDG)+ 任务心跳位图**——现状全库无看门狗(HAL 驱动源码也不在仓库),任何形态死机不可自恢复;另 `configASSERT` 为关中断死循环(连日志都不打)。**代码已落地并编译通过(2026-09-29)**:CubeMX 生成 IWDG(Prescaler=64/Reload=1249)+ `App/util/task_watchdog.{c,h}` 心跳位图 + 6 任务埋点 + `RCC_CSR` 复位原因锁存 + `configASSERT` 改造 | **剩台架验证**(故障注入 V2/V4、长跑 V5 ≥30 min);文档 §10 第 7~10 步待办 | **见 [`子系统设计/看门狗设计说明.md`](子系统设计/看门狗设计说明.md)**(§10 有实施状态表) | `审查记录/项目审查与优化建议报告.md` N-03a/b/c |
| N-03a | `configASSERT(x)` = `taskDISABLE_INTERRUPTS(); for(;;);`(`Inc/FreeRTOSConfig.h:163`)→ 断言时无任何输出 | 修复方案见 `看门狗设计说明.md` §4.6(改为"先记录后复位");N-03 实施时一并处理 | 同上 N-03b | | N-03a | `configASSERT(x)` = `taskDISABLE_INTERRUPTS(); for(;;);`(`Inc/FreeRTOSConfig.h`)→ 断言时无任何输出 | ✅ **已修(2026-09-29)**:改为 `vApplicationAssertFailed(__FILE__, __LINE__)`,打印文件名+行号后主动复位(`Src/freertos.c`);宏已迁入 `USER CODE BEGIN 1` 区防重生成丢失 | 同上 N-03b |
| N-03b | 启动段(`app_main_init` + `defaultTask` bring-up)在新方案下**无看门狗保护** | 显式代价:`看门狗设计说明.md` §4.5 决策 C + §9 R1;该段死机表现为"无输出 + LED 不闪" | 同上 N-03c | | N-03b | 启动段(`app_main_init` + `defaultTask` bring-up)在新方案下**无看门狗保护** | 显式代价(未变):`看门狗设计说明.md` §4.5 决策 C + §9 R1;该段死机表现为"无输出 + LED 不闪" | 同上 N-03c |
| N-03c | **CubeMX 重生成会覆盖 `USER CODE` 标记区之外的定制** | ⚠️ **2026-09-29 实测确认**:重生成覆盖 4 处(P0 `Src/iwdg.c` 自动启动、P1 `HardFault_Handler` 打回空死循环、P1 `FreeRTOSConfig.h` 两个加固宏被删、P2 `freertos.c` 中文注释);已全部恢复并加"重生成会删除"警示注释;**今后每次 CubeMX 重生成后须重跑本文档 §10.1 的核对清单** | 本次实施记录 |