学习目标
- 了解什么是看门狗
- 了解看门狗工作原理
- 了解ARM的独立看门狗和窗口看门够
- 掌握看门狗初始化和喂狗
学习内容
什么是看门狗
看门狗(Watchdog)是一种用于监视系统运行情况的硬件设备,它可以在系统出现故障或者卡死时自动重启系统,从而保证系统的稳定性和可靠性。
看门狗(Watchdog)在嵌入式系统中起着至关重要的作用,它通常是一种硬件计时器或计数器,用于监控系统的运行情况。其作用和重要性包括以下几个方面:
- 系统健壮性和稳定性: 看门狗能够监控系统的运行状态,一旦系统出现故障、死锁或意外情况,可以通过重启系统来恢复正常运行,确保系统的稳定性和可靠性。
- 防止死锁和程序错误: 当程序发生死循环、意外暂停或其他异常情况时,看门狗可以检测到系统无响应的状态并执行重启操作,从而防止系统永久性死锁。
- 系统保护和数据完整性: 通过定期喂狗操作,可以确保系统在正常运行期间不会因软件或硬件故障而丢失关键数据,从而保护系统的数据完整性和稳定性。
- 实时系统保障: 对于实时系统而言,看门狗可以帮助确保系统在规定的时间内完成任务,若任务未能及时完成,可以执行重启操作以确保系统的实时性能。
看门狗在嵌入式系统中的作用和重要性体现在提高系统的稳定性、保护数据完整性、预防死锁和程序错误、保障实时系统性能等方面。它是确保嵌入式系统安全可靠运行的重要保障手段之一。
ARM中的看门狗
独立看门狗定时器
有独立时钟源(IRC32K)。即使主时钟失效,FWDGT依然能保持正常工作状态,适用于需要独立环境且对计时精度要求不高的场合。
当内部向下计数器的计数值达到0,独立看门狗会产生一个系统复位。使能独立看门狗的寄存器写保护功能可以避免寄存器的值被意外的配置篡改。
窗口看门狗定时器
用来监测由软件故障导致的系统故障。窗口看门狗定时器开启后,7位向下递减计数器值逐渐减小。计数值达到0x3F时会产生系统复位(CNT[6]位被清0)。在计数器计数值达到窗口寄存器值之前,计数器的更新也会产生复位。因此软件需要在给定的区间内更新计数器。窗口看门狗定时器在计数器计数值达到0x40会产生一个提前唤醒标志,如果使能中断将会产生中断。窗口看门狗定时器时钟是由APB1时钟预分频而来。窗口看门狗定时器适用于需要精确计时的场合。
独立看门狗FWDGT
初始化配置
static void wtd_config() {
fwdgt_config(2 * 500, FWDGT_PSC_DIV64);
fwdgt_enable();
}
/* confiure FWDGT counter clock: 32KHz(IRC32K) / 64 = 0.5 KHz */
独立看门狗计数时钟计算:
- 独立看门狗具备独立晶振:32KHZ
- FWDGT_PSC_DIVx: x为分频系数,意思是降低晶振频率。例如为64时,32khz/64 = 0.5khz = 500hz,表示的是1秒钟计数500次。
- fwdgt_config(2 500, FWDGT_PSC_DIV64); 中的第一个参数就是计数值,通过分频我们可以知道1秒钟计数500次,那么我要设置为n秒,就需要 n500的计数值。
喂狗
fwdgt_counter_reload();
完整代码
```c
include “gd32f4xx.h”
include “systick.h”
include
include “main.h”
include “Usart0.h”
void Usart0_on_recv(uint8_t* data, uint32_t len) { printf(“recv: %s\r\n”, data); }
static void wtd_config() { fwdgt_config(2 * 500, FWDGT_PSC_DIV64); fwdgt_enable(); }
int main(void) { systick_config(); Usart0_init();
wtd_config();
printf("start\r\n");
while(1) {
delay_1ms(960);
/* reed dog */
fwdgt_counter_reload();
}
}
<a name="kVdqR"></a>
### 窗口看门狗WWDGT
<a name="c9K4p"></a>
#### 初始化配置
```c
static void wtd_config() {
rcu_periph_clock_enable(RCU_WWDGT);
/*
* System clock up to 240Mhz, PCLK1=60MHz
* set WWDGT clock = (PCLK1 (60MHz)/4096)/4 = 3662Hz (~273 us)
* set counter value to 127
* set window value to 80
* refresh window is: ~273 * (127-80)= 5.9ms < refresh window < ~273 * (127-0x3F) =17.5ms.
*/
wwdgt_config(127, 80, WWDGT_CFG_PSC_DIV4);
wwdgt_enable();
}
wwdgt_config(uint16_t counter, uint16_t window, uint32_t prescaler)
配置的是窗口时间,计算窗口时间是需要注意几个参数的含义。
- counter表示计数值,取值为0x00 - 0x7F
- window表示窗口值,取值为0x00 - 0x7F
- 窗口区间的初始值最小为0x3F
- 窗口计数是递减的,因此是 (counter - 初始值) 为最大时间计数,(counter - 窗口区间值)为最小时间计数
- 一个时钟计数,通过 主频/4096可以得到计数值,4096为12位向下计数器组成。
- 窗口计数器通过分频,得到一个时钟计数,主频/4096/分频系数
喂狗
完整代码
```c
include “gd32f4xx.h”
include “systick.h”
include
include “main.h”
include “Usart0.h”
void Usart0_on_recv(uint8_t* data, uint32_t len) { printf(“recv: %s\r\n”, data); }
static void wtd_config() { rcu_periph_clock_enable(RCU_WWDGT); /*
* System clock up to 240Mhz, PCLK1=60MHz
* set WWDGT clock = (PCLK1 (60MHz)/4096)/4 = 3662Hz (~273 us)
* set counter value to 127
* set window value to 80
* refresh window is: ~273 * (127-80)= 5.9ms < refresh window < ~273 * (127-0x3F) =17.5ms.
*/
wwdgt_config(127, 80, WWDGT_CFG_PSC_DIV4);
wwdgt_enable();
}
int main(void) { systick_config(); Usart0_init();
wtd_config();
printf("start\r\n");
while(1) {
delay_1ms(13);
/* update WWDGT counter */
wwdgt_counter_update(127);
}
}
练习题
- 实现独立看门狗喂狗
- 实现窗口看门狗喂狗