1 概述
DW_apb_wdt看门狗是新思科技推出的APB总线从设备IP核,主要用于在SoC中防止系统因程序跑飞或死锁而无法恢复。它有几个核心特征:
-
不可停止:看门狗一旦启动,硬件上就无法被软件停止。即使用户向控制寄存器写入禁用值,也不会生效。
-
必须定时喂狗:软件必须在设定的超时周期内执行"喂狗"操作,否则看门狗会产生中断或直接复位系统。
-
十六档可编程超时:硬件内部预置了16个超时周期(Timeout Period,简称TOP),每个TOP是一个32位的计数值,看门狗计数器从这个值开始递减计数,归零时触发超时事件。
-
两种响应模式:可通过控制寄存器配置超时后产生复位(RESET)还是先产生中断(IRQ)再复位。

2 寄存器总览
| 偏移量 | 寄存器名称(Linux 宏) | 功能简述 |
|---|---|---|
| 0x00 | WDOG_CONTROL_REG_OFFSET | 控制寄存器(WDT_CR):使能看门狗、选择响应模式 |
| 0x04 | WDOG_TIMEOUT_RANGE_REG_OFFSET | 超时范围寄存器(WDT_TORR):选择16档超时周期之一 |
| 0x08 | WDOG_CURRENT_COUNT_REG_OFFSET | 当前计数值寄存器(WDT_CURR):只读,查看剩余计数值 |
| 0x0c | WDOG_COUNTER_RESTART_REG_OFFSET | 计数器重启寄存器(WDT_CRR):写入固定值0x76触发"喂狗" |
3 核心寄存器详解
**控制寄存器:**控制寄存器决定看门狗是否使能,以及在超时时产生复位信号还是先产生中断。重点位定义如下:
| 位 | 字段名 | 功能说明 |
|---|---|---|
| Bit0 | EN (Enable) | 0:禁用看门狗;1:使能看门狗。看门狗一旦使能就无法停止,该位只能写一次,之后不能再改写。 |
| Bit1 | RM (Response Mode) | 响应模式选择。0:超时后产生复位(RESET);1:超时后先产生中断(IRQ),若中断未及时清除则最终复位。 |
**超时范围寄存器:**WDT_TORR用于从16档预设的超时周期中选择一档作为当前看门狗的计数值。
| 位 | 字段名 | 功能说明 |
|---|---|---|
| bit0-bit3 | TOP (Timeout Period) | 选择16档超时周期之一。TOP值范围0 ~ 15,分别对应硬件预置的16个不同的计数值。 |
| bit4-bit31 | Reserved | 保留位,写0,读忽略。 |
超时时间计算公式:
超时时间 = (TOP对应的计数值) × (1/参考时钟频率)
说明:参考时钟从设备树属性的clocks读取。
TOP 值对应的计数值(举例):
若 DW 看门狗采用标准默认的16档计数值,TOP值与计数值的对应关系如下:
TOP = 0 → 计数值 = 0x00001000(即 4096)
TOP = 1 → 计数值 = 0x00002000(即 8192)
TOP = 2 → 计数值 = 0x00004000(即 16384)
...
TOP = 15 → 计数值 = 0x80000000(即 2,147,483,648)
说明:芯片厂商对DW看门狗的TOP值做了定制化修改,则应在设备树中通过snps,watchdog-tops属性指定自定义的16档计数值列表。
**当前计数值寄存器:**只读寄存器,存放看门狗计数器当前的递减计数值。软件可以通过读取该值监控剩余的超时时间,用于调试。
计数重启寄存器: WDT_CRR是喂狗操作的核心寄存器。向该寄存器写入一个固定的魔数0x76,会触发硬件将当前TOP对应的计数值重新装入计数器,计数器从该值重新开始递减。
4 超时时间计算
假设参考时钟频率为freq(单位 Hz),TOP值对应的计数值为top_val,则超时时间计算公式为:
超时时间(秒)= top_val/freq
例如:freq = 24 MHz = 24,000,000 Hz,TOP = 2(计数值 = 16,384)则
超时时间 = 16384 / 24000000 ≈ 0.0006827 秒 ≈ 0.68 ms
5 编程概要
enable_wdt_clock(); //使能时钟(与具体SoC相关)
write32(base + WDT_TORR, 0x5); 配置超时档位(TOP = 5)
write32(base + WDT_CR, (0x1 << 1) | 0x1); //配置控制寄存器:响应模式 = 复位,并启用看门狗,RM=1(先中断后复位),EN=1
write32(base + WDT_CRR, 0x76); 启动看门狗(喂狗)
while (1) { //周期性喂狗(例如在定时器中断或主循环中)
// ... 应用逻辑
write32(base + WDT_CRR, 0x76);
delay_ms(feed_interval_ms);
}