fix(DLD154V4B): 修复 WDT_DIV 分频枚举传值 bug — 实际分频 4 导致 410ms 超时不断复位

现场实测 LIMIT=100 (500ms 喂狗) 不断复位重启, 改 50 正常。
根因: wdt_divider_set() 参数是枚举值 (WDT_CLK_DIV_16=0x02),
宏误传 16 (0b10000) -> 3bit 寄存器截断为 0 = WDT_CLK_DIV_4
-> 实际分频 4, 超时 4x4096/40k = 410ms < 500ms 喂狗周期。
修复: WDT_DIV=2 (枚举值) + (wdt_division_type) 显式转换。
隔离测试 mock 升级为 3bit 截断+反推分频, 复现 bug 并断言修复。
vd960Loop 原实现用 WDT_CLK_DIV_64 枚举写法, 无此问题。
This commit is contained in:
wangfq
2026-08-28 09:08:42 +08:00
parent 8f43f8f1c9
commit 794e097587
4 changed files with 15 additions and 5 deletions
+11 -1
View File
@@ -35,6 +35,16 @@ V4B 是全产品线唯一**无看门狗**的型号(对比:M1H 有 WDT_CONTR
- 隔离测试(host gcc mock wdt_* 驱动)5 项断言全过:init 配置、10s 喂狗 20 次(500ms 精确)、ISR 死不喂狗、边界 99/100 tick - 隔离测试(host gcc mock wdt_* 驱动)5 项断言全过:init 配置、10s 喂狗 20 次(500ms 精确)、ISR 死不喂狗、边界 99/100 tick
- 待现场验证:实际复位时间(LSI 实际频率),用 `RST_REASON` 类机制确认复位源 - 待现场验证:实际复位时间(LSI 实际频率),用 `RST_REASON` 类机制确认复位源
### ⚠ 现场发现并修复:WDT_DIV 传值 bugV2.10.1
**现象**:现场实测 `WDT_COUNTER_LIMIT=100`(500ms 喂狗)不断复位重启,改为 50(250ms)才正常。
**根因**`wdt_divider_set()` 参数是**枚举值**不是分频数值——`WDT_CLK_DIV_16 = 0x02`,寄存器只取低 3 位。宏误写 `WDT_DIV=16`0b10000)→ 寄存器写入 0 = `WDT_CLK_DIV_4`**实际分频 4,实际超时 410ms < 喂狗周期 500ms** → 每次喂狗前已超时,不断复位。
**修复**`#define WDT_DIV 2`(枚举值)+ 调用处显式 `(wdt_division_type)` 转换;隔离测试升级 mock 为"寄存器 3bit 截断 + 反推实际分频",复现 bug 机制并断言修复后超时 1638ms > 500ms。
**对照教训**vd960Loop 原实现用 `wdt_divider_set(WDT_CLK_DIV_64)` 枚举写法 ✓ 无此问题——**AT32 WDT 分频参数一律用枚举常量,勿传数值**。
--- ---
## 2026-08-28 — 平坦性离开判定默认关闭(现场实测不理想) ## 2026-08-28 — 平坦性离开判定默认关闭(现场实测不理想)
@@ -601,7 +611,7 @@ if (dev >= dlt_ORG × 4) {
| 版本 | 时间 | 说明 | | 版本 | 时间 | 说明 |
|------|------|------| |------|------|------|
| V2.10 | 2026-08-28 | 新增 IWDT 硬件看门狗(超时≈1.64s,双保险喂狗) | | V2.10 | 2026-08-28 | 新增 IWDT 硬件看门狗(超时≈1.64s,双保险喂狗);修复 WDT_DIV 分频枚举传值 bug(勿传 16,用 WDT_CLK_DIV_16 |
| V2.9 | 2026-08-28 | 平坦性离开判定默认关闭(现场实测不理想),切回简单 cnt_release 防抖 | | V2.9 | 2026-08-28 | 平坦性离开判定默认关闭(现场实测不理想),切回简单 cnt_release 防抖 |
| V2.8 | 2026-08-27 | 灵敏度最高档 SENS=3 阈值 10→20、离开 9→14(防误触发);清理 g_input_div 重复定义 | | V2.8 | 2026-08-27 | 灵敏度最高档 SENS=3 阈值 10→20、离开 9→14(防误触发);清理 g_input_div 重复定义 |
| V2.7 | 2026-06-30 | 验收标准 + 发展路线图文档 | | V2.7 | 2026-06-30 | 验收标准 + 发展路线图文档 |
+2 -2
View File
@@ -687,7 +687,7 @@ DLD154V4B/
// 看门狗参数 (IWDT, V2.10 新增) // 看门狗参数 (IWDT, V2.10 新增)
#define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms × 100) #define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms × 100)
#define WDT_DIV 16 // LSI 分频 #define WDT_DIV 2 // IWDT 分频枚举值: 2 = WDT_CLK_DIV_16 (实际分频 16, 勿传 16!)
#define WDT_RLD 4095 // 12bit 重装载 → 超时 ≈ 1.64s #define WDT_RLD 4095 // 12bit 重装载 → 超时 ≈ 1.64s
``` ```
@@ -697,7 +697,7 @@ AT32F421 独立看门狗(IWDT),双保险喂狗模式(对齐 DLD154Pro V3
| 环节 | 实现 | | 环节 | 实现 |
|------|------| |------|------|
| 使能 | `main()``wdt_init()`:分频 16 + 重装载 4095 + 立即喂一次 | | 使能 | `main()``wdt_init()`:分频 16(枚举 `WDT_CLK_DIV_16`+ 重装载 4095 + 立即喂一次 |
| 超时 | ≈ 1.64sLSI≈40kHz`16×4096/40k` | | 超时 | ≈ 1.64sLSI≈40kHz`16×4096/40k` |
| 活性计数 | TMR15 ISR 每 5ms `g_wdg_counter++` | | 活性计数 | TMR15 ISR 每 5ms `g_wdg_counter++` |
| 喂狗 | 主循环每轮 `poll_wdg()`:计数达 100500ms)才 `wdt_counter_reload()` | | 喂狗 | 主循环每轮 `poll_wdg()`:计数达 100500ms)才 `wdt_counter_reload()` |
@@ -52,7 +52,7 @@
* 超时 = WDT_DIV x (WDT_RLD+1) / LSI(约40kHz) 约 1.64s * 超时 = WDT_DIV x (WDT_RLD+1) / LSI(约40kHz) 约 1.64s
*===========================================================================*/ *===========================================================================*/
#define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms x 100) #define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms x 100)
#define WDT_DIV 16 // LSI 分频 #define WDT_DIV 2 // IWDT 分频枚举值: 2 = WDT_CLK_DIV_16 (实际分频 16; 勿传 16!)
#define WDT_RLD 4095 // 12bit 重装载 -> 超时约 1.64s #define WDT_RLD 4095 // 12bit 重装载 -> 超时约 1.64s
#define WINDOW_ORIGIN 500 // 基线跟踪窗口 (500 × 10ms = 5s) #define WINDOW_ORIGIN 500 // 基线跟踪窗口 (500 × 10ms = 5s)
@@ -318,7 +318,7 @@ void poll_yellow_led(void)
void wdt_init(void) void wdt_init(void)
{ {
wdt_register_write_enable(TRUE); wdt_register_write_enable(TRUE);
wdt_divider_set(WDT_DIV); wdt_divider_set((wdt_division_type)WDT_DIV); // WDT_DIV=2 -> WDT_CLK_DIV_16
wdt_reload_value_set(WDT_RLD); wdt_reload_value_set(WDT_RLD);
wdt_enable(); wdt_enable();
wdt_counter_reload(); // 使能后立即喂一次, 给 FreeRTOS 启动留足时间 wdt_counter_reload(); // 使能后立即喂一次, 给 FreeRTOS 启动留足时间