实现独立看门狗: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:
@@ -28,6 +28,53 @@
|
||||
|
||||
/* 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) */
|
||||
(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) 时间子系统初始化(尽早完成,后续所有日志带时间戳)
|
||||
* sd2506_init() 从 RTC 读取初始时间
|
||||
|
||||
Reference in New Issue
Block a user