本章我们来学习下看门狗(watchdog),看门狗是一种形象的说法,他是一种用于监测单片机程序运行状态的芯片,由于单片机的工作常常会受到来自外界电磁场的干扰,造成各种寄存器和内存的数据混乱,导致程序指针错误、取出错误的程序指令等,都有可能会陷入死循环,程序的正常运行被打断,导致整个系统的陷入停滞状态,发生不可预料的后果。有了看门狗之后就会对系统进行复位;
看门狗其实就是一个需要在设定一定时间内被复位的计数器,如果没有按时复位,则会强制系统复位。在看门狗启动前需要配置超时时间,当看门狗启动后,计数器开始自动计数,经过一定时间,如果没有被复位,计数器溢出就会对CPU产生一个复位信号使系统重启(俗称“被狗咬”)。要保证系统正常运行时,需要在看门狗超时时间内重置看门狗计数器(俗称“喂狗”)。
之前讲STM32时候也有过介绍,详细了解的话可以参考:STM32开发(11)----CubeMX配置独立看门狗(IWDG) STM32开发(12)----CubeMX配置WWDG
WDT是外围总线(APB)的一种从外设,并且也是“同步化硬件组件设计”的组成部分,具有两个WDT,分别为WDT0和WDT1看门狗定时器,主要包含的模块有一个APB从接口,一个当前计数器同步的寄存器模块,一个随着计数器递减的中断/系统重置模块和逻辑控制电路,一个同步时钟域来为异步时钟同步做支持。
看门狗定时器支持如下设置:
? APB 总线宽度可配置为8、16 和32 位
? 时钟计数器从某一个设定的值递减到0 来指示时间的计时终止
? 可选择的外部时钟使能信号,用于控制计数器的计数速率
? 一个时钟超时WDT 可以执行以下任务:
– 产生一个系统复位信号
– 首先产生一个中断,即使该位是否已经被中断服务清除,其次它会产生一个系统复位信号
? 占空比可编程调节
? 可编程和硬件设定计数器起始值
? 计数器重新计时保护
? 暂停模式,仅当使能外部暂停信号时
? WDT 偶然禁用保护
? 测试模式,用来进行计数器功能测试(递减操作)
? 外部异步时钟支持。当该项功能启用时,将会产生时钟中断和系统重置信号,即使APB 总线时钟关闭的情况下。
4.SDK中对应API功能
板级对应的头文件wdt.h
WDT看门狗在开发单片机中作用巨大,可以在程序出现死机的情况自动重启系统,而不需要手动操作。
为用户提供以下接口:
? wdt_init:配置看门狗参数,启动看门狗,不使用中断的话,将on_irq设置为NULL。返回值为看门狗实际超时时间,一般比设置的时间稍微大一些。
? wdt_start(0.6.0 后不再支持,请使用wdt_init)
? wdt_stop:关闭看门狗。
? wdt_feed:重置看门狗计时器,俗称喂狗。
? wdt_clear_interrupt:清除中断,如果在中断函数中清除中断,看门狗不会重启。
本实验实现一个喂狗的过程,前面我们先在超时时间内进行喂狗,这样不会触发看门狗的中断处理函数,后面我们停止喂狗,触发我们定义的看门狗中断处理函数。
新建wdt文件夹,在文件夹下新建main.c文件
#include <stdio.h>
#include <unistd.h>
#include "wdt.h"
#include "sysctl.h"
#define WDT_TIMEOUT_REBOOT 1
/**
* Function wdt0_irq_cb
* @brief 看门狗中断回调
* @param[in] void
* @param[out] void
* @retval 0
* @par History 无
*/
int wdt0_irq_cb(void *ctx)
{
#if WDT_TIMEOUT_REBOOT //这种情况下系统会重启
printf("%s:The system will reboot soon!\n", __func__);
while(1);
#else //这种情况下系统不重启,重置WDT状态
printf("%s:The system is busy but not reboot!\n", __func__);
wdt_clear_interrupt(WDT_DEVICE_0);
#endif
return 0;
}
/**
* Function main
* @brief 主函数,程序的入口
* @param[in] void
* @param[out] void
* @retval 0
* @par History 无
*/
int main(void)
{
/* 打印系统启动信息 */
printf("system start!\n");
/* 记录feed的次数 */
int times = 0;
/* 系统中断初始化 */
plic_init();
sysctl_enable_irq();
/* 启动看门狗,设置超时时间为2秒后调用中断函数wdt0_irq_cb */
int timeout = wdt_init(WDT_DEVICE_0, 2000, wdt0_irq_cb, NULL);
/* 打印看门狗实际超时的时间 */
printf("wdt timeout is %d ms!\n", timeout);
while(1)
{
sleep(1);
if(times++ < 10)
{
/* 打印feed的次数 */
printf("wdt_feed %d times!\n", times);
/* 重置看门狗的计时器,重新开始计时 */
wdt_feed(WDT_DEVICE_0);
}
}
}
代码写好后,我们开始编译,注意:如果你编译过程中出现错误,可以先make clean掉之前生成的过程文件,重新生成
cd build
//注意这里的目标文件目录改成gpio,和刚才新建的文件夹名称一致
cmake .. -DPROJ=wdt -G "MinGW Makefiles"
make
编译完成后,在build文件夹下会生成wdt.bin文件。
使用type-C数据线连接电脑与K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到K210开发板上。
然后我们一起来看下实验现象,在停止喂狗之后,系统重启
看门狗的作用是当没有在设定的时间内喂狗,则系统会发送中断使系统强制重启,看门狗必须在系统正常运行的情况下喂狗,这样系统异常时就能够及时重启系统,看门狗的定时中断是实际超时时间的一半,需要在这个时间内喂狗。