From 8f43f8f1c9c67d7f92f78b97b62be3d1847f2247 Mon Sep 17 00:00:00 2001 From: wangfq Date: Fri, 28 Aug 2026 08:56:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(DLD154V4B):=20V2.10=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20IWDT=20=E7=A1=AC=E4=BB=B6=E7=9C=8B=E9=97=A8=E7=8B=97?= =?UTF-8?q?=EF=BC=88=E8=B6=85=E6=97=B6=E2=89=881.64s=EF=BC=8C=E5=8F=8C?= =?UTF-8?q?=E4=BF=9D=E9=99=A9=E5=96=82=E7=8B=97=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 对齐 DLD154Pro V3.03 方案: TMR15 ISR 5ms 递增 g_wdg_counter, 主循环 poll_wdg() 每 500ms 喂狗, 超时 16×4096/40k ≈ 1.64s - 双保险: ISR 死→计数不涨→永不喂狗; 主循环死→poll_wdg 不执行→复位 - main() 使能后立即喂一次, 给 FreeRTOS 启动留足时间 - 隔离测试 5 项断言全过 (init 配置/10s 喂狗 20 次/ISR 死不喂/边界 99-100 tick) - 文档同步: technical-spec(架构图+§13.1 机制) / release-notes(V2.10) / product-manual(特性+版本) / roadmap / devlog --- docs/devlog.md | 34 +++++++++++++++++++ docs/product-manual.md | 2 ++ docs/release-notes.md | 12 ++++++- docs/roadmap.md | 3 +- docs/technical-spec.md | 28 +++++++++++++-- .../at32f421_freertos_demo/inc/TaskLoop.h | 12 +++++++ .../at32f421_freertos_demo/src/TaskLoop.c | 28 +++++++++++++++ utilities/at32f421_freertos_demo/src/main.c | 2 ++ 8 files changed, 117 insertions(+), 4 deletions(-) diff --git a/docs/devlog.md b/docs/devlog.md index 9488de2..58d3776 100644 --- a/docs/devlog.md +++ b/docs/devlog.md @@ -4,6 +4,39 @@ --- +## 2026-08-28 — 新增 IWDT 硬件看门狗(V2.10) + +### 背景 + +V4B 是全产品线唯一**无看门狗**的型号(对比:M1H 有 WDT_CONTR、PD132 系有 IWDG/WWDG、154Pro V3.03 有 WWDG 558ms)。现场若主循环卡死/FreeRTOS 调度异常,表现为"假活"——指示灯正常但检测逻辑已死,只能断电恢复。 + +### 实现(对齐 154Pro V3.03 双保险模式) + +```c +// main(): wdt_init() — IWDT 分频16 + 重装载4095, 使能后立即喂一次 +// TMR15 ISR: g_wdg_counter++ (5ms) +// 主循环: poll_wdg() — 计数达 100 (500ms) 才 wdt_counter_reload() +``` + +- **超时** ≈ 1.64s(LSI≈40kHz:16×4096/40k),喂狗周期 500ms,余量 >3× +- **双保险语义**:ISR 死 → 计数不涨 → 永不喂狗;主循环死 → poll_wdg 不执行 → 超时复位 +- FreeRTOS 调度失败/任务创建失败 → 无人喂狗 → 复位(避免"假活") + +### 涉及文件 + +| 文件 | 变更 | +|------|------| +| `src/main.c` | `Timr6_Init()` 后调 `wdt_init()` | +| `src/TaskLoop.c` | +`g_wdg_counter` + `wdt_init()` + `poll_wdg()`;TMR15 ISR 计数;主循环喂狗 | +| `inc/TaskLoop.h` | +WDT 宏 + extern + 函数声明 | + +### 验证 + +- 隔离测试(host gcc mock wdt_* 驱动)5 项断言全过:init 配置、10s 喂狗 20 次(500ms 精确)、ISR 死不喂狗、边界 99/100 tick +- 待现场验证:实际复位时间(LSI 实际频率),用 `RST_REASON` 类机制确认复位源 + +--- + ## 2026-08-28 — 平坦性离开判定默认关闭(现场实测不理想) ### 背景 @@ -568,6 +601,7 @@ if (dev >= dlt_ORG × 4) { | 版本 | 时间 | 说明 | |------|------|------| +| V2.10 | 2026-08-28 | 新增 IWDT 硬件看门狗(超时≈1.64s,双保险喂狗) | | V2.9 | 2026-08-28 | 平坦性离开判定默认关闭(现场实测不理想),切回简单 cnt_release 防抖 | | V2.8 | 2026-08-27 | 灵敏度最高档 SENS=3 阈值 10→20、离开 9→14(防误触发);清理 g_input_div 重复定义 | | V2.7 | 2026-06-30 | 验收标准 + 发展路线图文档 | diff --git a/docs/product-manual.md b/docs/product-manual.md index 5e7d257..456c9dc 100644 --- a/docs/product-manual.md +++ b/docs/product-manual.md @@ -18,6 +18,7 @@ DLD154V4B 是一款基于 ARM Cortex-M4 微控制器的**单通道环形线圈 - **诊断黄灯**:断开/重连次数编码闪烁,现场故障一目了然 - **灵敏度 4 级可调**:通过 DIP 开关配置,0.031% ~ 0.33% 频率变化检测 - **双输出模式**:存在输出 / 脉冲输出可选 +- **看门狗自恢复**:硬件 IWDT(超时≈1.64s),系统异常自动复位,现场免维护 - **宽频率范围**:支持 30 ~ 200 kHz 线圈频率 ### 1.2 适用场景 @@ -245,6 +246,7 @@ DLD154V4B 是一款基于 ARM Cortex-M4 微控制器的**单通道环形线圈 | V2.7 | 2026-06-30 | 验收标准 + 发展路线图文档 | | V2.8 | 2026-08-27 | 灵敏度最高档 SENS=3 阈值 10→20、离开 9→14(防误触发) | | V2.9 | 2026-08-28 | 平坦性离开判定默认关闭(现场实测不理想),切回简单防抖 | +| V2.10 | 2026-08-28 | 新增 IWDT 硬件看门狗(超时≈1.64s,双保险喂狗) | --- diff --git a/docs/release-notes.md b/docs/release-notes.md index 69a5a67..f759c50 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,6 +1,6 @@ # DLD154V4B 产品发布说明 -> 固件版本 **V2.9** | 发布日期 2026-08-28 +> 固件版本 **V2.10** | 发布日期 2026-08-28 > 单路线圈车辆检测器 · ARM Cortex-M4 · 单路 IIR + 智能基线 --- @@ -76,6 +76,14 @@ if ((Origin - dlt_ORG) < CAPVD) { // 回升至距基线不足 dlt | **基线冻结超时** | 无(永久冻结) | 稳定 10s 后自动更新 | 环境变化免复位 | | **冻结稳定性检查** | — | ±2% 窗口验证 | 防止波动值被判为新常态 | +### 6. 硬件看门狗自恢复(V2.10) + +AT32F421 独立看门狗(IWDT),超时 ≈1.64s,**双保险喂狗**: + +- TMR15 ISR 每 5ms 递增活性计数;主循环 `poll_wdg()` 每 500ms 喂狗 +- ISR 死 / 主循环卡死 / FreeRTOS 调度失败 → 无人喂狗 → 自动复位,系统自恢复 +- 现场免人工干预,杜绝"假活"(指示灯亮但逻辑已死) + --- ## 技术规格速览 @@ -94,6 +102,7 @@ if ((Origin - dlt_ORG) < CAPVD) { // 回升至距基线不足 dlt | 调试口 | TTL 电平 Tx (9600,8N1) | | 供电 | DC 10~30V 宽压,< 2W | | 温度 | -40°C ~ +85°C | +| 看门狗 | **IWDT 硬件看门狗,超时 ≈1.64s**(双保险喂狗,V2.10 新增) | | CPU 占用 | < 5% @120MHz | | 基线冻结超时 | 10s(稳定后自动恢复) | @@ -139,6 +148,7 @@ if ((Origin - dlt_ORG) < CAPVD) { // 回升至距基线不足 dlt | V2.7 | 06-30 | 验收标准 + 发展路线图文档 | | V2.8 | 08-27 | 灵敏度最高档 SENS=3 阈值 10→20、离开 9→14(防误触发) | | **V2.9** | **08-28** | **平坦性离开判定默认关闭(现场实测不理想),切回简单 cnt_release 防抖** | +| **V2.10** | **08-28** | **新增 IWDT 硬件看门狗(超时≈1.64s,双保险喂狗)** | --- diff --git a/docs/roadmap.md b/docs/roadmap.md index 55d5963..c7f9a1d 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -10,7 +10,7 @@ |------|------|------|------|-------|---------|---------|---------| | M1H | 8051 12MHz | CD4060 ÷32 | 50ms | 162ms | 单次阈值 | 单次阈值 | 拨码 | | TLD-110 | 8051 | CD4060 ÷32 | 50ms | 162ms | 单次阈值 | 单次阈值 | 拨码 | -| **V4B V2.9** | M4 120MHz | TIM3 ÷2 | **10ms** | **32ms** | **3次确认+斜率限幅** | **简单防抖(平坦性默认关)** | 拨码 | +| **V4B V2.10** | M4 120MHz | TIM3 ÷2 | **10ms** | **32ms** | **3次确认+斜率限幅** | **简单防抖(平坦性默认关)** | 拨码 | ### 1.1 V4B 相比 M1H 的核心突破 @@ -23,6 +23,7 @@ | 离开判定 | 单阈值 | **滞回 + 3 次确认(平坦性可选,默认关)** | 防瞬态误落杆 | | 基线保护 | 无(有车也跟踪) | **冻结 + 10s 超时 + 稳定性检查** | 防污染 + 不死锁 | | 线圈诊断 | 无 | **黄灯断开次数编码** | 现场可排障 | +| 看门狗 | WDT_CONTR | **IWDT 1.64s 双保险喂狗**(V2.10) | 防"假活",现场免维护 | | 代码量 | ~1200 行 (未精简) | **~945 行** | 功能更多,代码更少 | --- diff --git a/docs/technical-spec.md b/docs/technical-spec.md index 50f8c38..e37f02b 100644 --- a/docs/technical-spec.md +++ b/docs/technical-spec.md @@ -42,8 +42,9 @@ FreeRTOS Kernel (CMSIS-RTOS v2) │ ├── poll_green_led() — 绿灯驱动 │ └── poll_yellow_led() — 黄灯故障编码 ├── TMR3_ISR() — 线圈频率捕获 -├── TMR15_ISR() — 5ms 系统 tick (LED 驱动) -└── TMR14_PWM() — 红灯呼吸 +├── TMR15_ISR() — 5ms 系统 tick (LED 驱动 + 看门狗活性计数) +├── TMR14_PWM() — 红灯呼吸 +└── IWDT — 硬件看门狗 (超时≈1.64s, main 使能, 主循环 poll_wdg 喂狗) ``` --- @@ -683,8 +684,31 @@ DLD154V4B/ #define ENTRY_CONFIRM 3 // 进入确认: 连续 N 次低于阈值 #define FREEZE_TIMEOUT 1000 // 冻结超时: ~10s @ 10ms/tick #define FREEZE_STABILITY_RATE 2 // 稳定性窗口: 参考值的 ±2% + +// 看门狗参数 (IWDT, V2.10 新增) +#define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms × 100) +#define WDT_DIV 16 // LSI 分频 +#define WDT_RLD 4095 // 12bit 重装载 → 超时 ≈ 1.64s ``` +### 13.1 看门狗机制(IWDT,V2.10 新增) + +AT32F421 独立看门狗(IWDT),双保险喂狗模式(对齐 DLD154Pro V3.03 方案): + +| 环节 | 实现 | +|------|------| +| 使能 | `main()` 中 `wdt_init()`:分频 16 + 重装载 4095 + 立即喂一次 | +| 超时 | ≈ 1.64s(LSI≈40kHz,`16×4096/40k`) | +| 活性计数 | TMR15 ISR 每 5ms `g_wdg_counter++` | +| 喂狗 | 主循环每轮 `poll_wdg()`:计数达 100(500ms)才 `wdt_counter_reload()` | + +**双保险语义**: +- TMR15 ISR 死 → 计数不涨 → 永不喂狗 → 1.64s 后复位 +- 主循环死(阻塞/死循环不走喂狗点)→ poll_wdg 不执行 → 1.64s 后复位 +- FreeRTOS 调度失败 / 任务创建失败 → 无人喂狗 → 复位(期望行为,避免"假活") + +> ⚠ 喂狗周期 500ms 必须远小于超时 1.64s;修改 WDT_DIV/WDT_RLD 时保持 `喂狗周期 < 超时/2`。 + --- ## 14. 关键专利 diff --git a/utilities/at32f421_freertos_demo/inc/TaskLoop.h b/utilities/at32f421_freertos_demo/inc/TaskLoop.h index dd0df5c..d9d1fc2 100644 --- a/utilities/at32f421_freertos_demo/inc/TaskLoop.h +++ b/utilities/at32f421_freertos_demo/inc/TaskLoop.h @@ -46,6 +46,15 @@ *===========================================================================*/ #define USE_FLATNESS_EXIT 0 +/*=========================================================================== + * 看门狗 (IWDT) - V2.10 新增 + * 双保险模式: TMR15 ISR 5ms 递增 g_wdg_counter, 主循环 poll_wdg() 每 500ms 喂狗 + * 超时 = WDT_DIV x (WDT_RLD+1) / LSI(约40kHz) 约 1.64s + *===========================================================================*/ +#define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms x 100) +#define WDT_DIV 16 // LSI 分频 +#define WDT_RLD 4095 // 12bit 重装载 -> 超时约 1.64s + #define WINDOW_ORIGIN 500 // 基线跟踪窗口 (500 × 10ms = 5s) /*=========================================================================== @@ -126,6 +135,7 @@ extern uint16_t Hold_CNT; // 有限存在计数器 extern uint8_t loop1_INCNT; // 进入延时计数 extern uint8_t loop1_OUTCNT; // 离开延时/脉冲宽度计数 extern uint8_t TM1cnt; // 50ms tick 分频计数 +extern volatile uint16_t g_wdg_counter; // 看门狗活性计数 (TMR15 5ms 递增) /*=========================================================================== * 拨码开关状态 @@ -183,5 +193,7 @@ void poll_yellow_led(void); void poll_green_led(void); void LEDA_ON_OFF(void); void vd1_task(void); +void wdt_init(void); +void poll_wdg(void); #endif /* __TASKLOOP_H__ */ diff --git a/utilities/at32f421_freertos_demo/src/TaskLoop.c b/utilities/at32f421_freertos_demo/src/TaskLoop.c index 4752ffe..931f68a 100644 --- a/utilities/at32f421_freertos_demo/src/TaskLoop.c +++ b/utilities/at32f421_freertos_demo/src/TaskLoop.c @@ -35,6 +35,7 @@ uint32_t loop1_ORG_SUM; uint16_t loop1_ORG_CNT; uint16_t loop1_dlt_ORG; uint8_t Flt_Reg; +volatile uint16_t g_wdg_counter = 0; // 看门狗活性计数 (TMR15 ISR 5ms 递增) /* M4 优化: 快速 IIR + 进入确认 */ uint8_t loop1_entry_cnt; @@ -309,6 +310,29 @@ void poll_yellow_led(void) } } +/*=========================================================================== + * 看门狗 (IWDT) - V2.10 新增 + * 双保险: TMR15 ISR 5ms 递增 g_wdg_counter, 主循环 poll_wdg() 每 500ms 喂狗 + * ISR 死 -> counter 不涨 -> 永不喂狗; 主循环死 -> poll_wdg 不执行 -> 超时复位 + *===========================================================================*/ +void wdt_init(void) +{ + wdt_register_write_enable(TRUE); + wdt_divider_set(WDT_DIV); + wdt_reload_value_set(WDT_RLD); + wdt_enable(); + wdt_counter_reload(); // 使能后立即喂一次, 给 FreeRTOS 启动留足时间 + g_wdg_counter = 0; +} + +void poll_wdg(void) +{ + if (g_wdg_counter >= WDT_COUNTER_LIMIT) { // 100 x 5ms = 500ms + g_wdg_counter = 0; + wdt_counter_reload(); + } +} + /*=========================================================================== * 初始化所有状态变量(对齐 M1H INIT_VD) *===========================================================================*/ @@ -485,6 +509,9 @@ void TMR15_GLOBAL_IRQHandler(void) if (tmr_interrupt_flag_get(TMR15, TMR_OVF_FLAG) != RESET) { + /*--- 看门狗活性计数 (5ms) ---*/ + g_wdg_counter++; + /*--- 初始化阶段红灯快闪 (200ms 周期) ---*/ if (!g_loop_power_up_state) { _counter1_init++; @@ -909,6 +936,7 @@ void loop_task_function(void *pvParameters) } #endif + poll_wdg(); // IWDT 喂狗 (500ms, TMR15 活性双保险) vTaskDelay(10); // 10ms tick, M4 优化: 双路 IIR + 进入确认 + 斜率限幅 } } diff --git a/utilities/at32f421_freertos_demo/src/main.c b/utilities/at32f421_freertos_demo/src/main.c index 19c2a55..d61276c 100644 --- a/utilities/at32f421_freertos_demo/src/main.c +++ b/utilities/at32f421_freertos_demo/src/main.c @@ -229,6 +229,8 @@ int main(void) loop_timer_io_init(); Timr6_Init(); + + wdt_init(); // IWDT 看门狗使能 (超时约1.64s), 主循环 poll_wdg() 喂狗