# WATCHDOG
- [概述](#section14918241977)
- [接口说明](#section20177131219818)
- [使用指导](#section10103184312813)
- [使用流程](#section10181195910815)
- [打开看门狗设备](#section66089201107)
- [获取看门狗状态](#section786624341011)
- [设置超时时间](#section182386137111)
- [获取超时时间](#section1883310371114)
- [启动看门狗](#section82501405123)
- [喂狗](#section3547530101211)
- [停止看门狗](#section944595841217)
- [关闭看门狗设备](#section96561824121311)
- [使用实例](#section1724514523135)
## 概述
看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。
### 接口说明
**表 1** 看门狗 API接口功能介绍
功能分类
|
接口名
|
描述
|
打开/关闭看门狗
|
WatchdogOpen
|
打开看门狗设备
|
WatchdogClose
|
关闭看门狗设备
|
启动/停止看门狗
|
WatchdogStart
|
启动看门狗
|
WatchdogStop
|
停止看门狗
|
设置/获取超时时间
|
WatchdogSetTimeout
|
设置看门狗超时时间
|
WatchdogGetTimeout
|
获取看门狗超时时间
|
获取看门狗状态
|
WatchdogGetStatus
|
获取看门狗状态
|
清除看门狗定时器
|
WatchdogFeed
|
清除看门狗定时器(喂狗)
|
> **说明:**
>本文涉及看门狗的所有接口,仅限内核态使用,不支持在用户态使用。
## 使用指导
### 使用流程
使用看门狗的一般流程如[图1](#fig19134125410189)所示。
**图 1** 看门狗使用流程图

### 打开看门狗设备
在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备:
int32\_t WatchdogOpen\(int16\_t wdtId\);
**表 2** WatchdogOpen参数和返回值描述
参数
|
参数描述
|
wdtId
|
看门狗设备号
|
返回值
|
返回值描述
|
NULL
|
打开失败
|
DevHandle类型指针
|
看门狗设备句柄
|
```
DevHandle handle = NULL;
handle = WatchdogOpen(0); /* 打开0号看门狗设备 */
if (handle == NULL) {
HDF_LOGE("WatchdogOpen: failed, ret %d\n", ret);
return;
}
```
### 获取看门狗状态
int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\);
**表 3** WatchdogGetStatus参数和返回值描述
参数
|
参数描述
|
handle
|
看门狗设备句柄
|
status
|
获取到的启动状态指针
|
返回值
|
返回值描述
|
0
|
获取成功
|
负数
|
获取失败
|
```
int32_t ret;
int32_t status;
/* 获取Watchdog启动状态 */
ret = WatchdogGetStatus(handle, &status);
if (ret != 0) {
HDF_LOGE("WatchdogGetStatus: failed, ret %d\n", ret);
return;
}
```
### 设置超时时间
int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\);
**表 4** WatchdogSetTimeout参数和返回值描述
参数
|
参数描述
|
handle
|
看门狗设备句柄
|
seconds
|
超时时间,单位为秒
|
返回值
|
返回值描述
|
0
|
设置成功
|
负数
|
设置失败
|
```
int32_t ret;
uint32_t timeOut = 60;
/* 设置超时时间,单位:秒 */
ret = WatchdogSetTimeout(handle, timeOut);
if (ret != 0) {
HDF_LOGE("WatchdogSetTimeout: failed, ret %d\n", ret);
return;
}
```
### 获取超时时间
int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\);
**表 5** WatchdogGetTimeout参数和返回值描述
参数
|
参数描述
|
handle
|
看门狗设备句柄
|
seconds
|
接收超时时间的指针,单位为秒
|
返回值
|
返回值描述
|
0
|
获取成功
|
负数
|
获取失败
|
```
int32_t ret;
uint32_t timeOut;
/* 获取超时时间,单位:秒 */
ret = WatchdogGetTimeout(handle, &timeOut);
if (ret != 0) {
HDF_LOGE("WatchdogGetTimeout: failed, ret %d\n", ret);
return;
}
```
### 启动看门狗
int32\_t WatchdogStart\(DevHandle handle\);
**表 6** WatchdogStart参数和返回值描述
参数
|
参数描述
|
handle
|
看门狗设备句柄
|
返回值
|
返回值描述
|
0
|
启动成功
|
负数
|
启动失败
|
```
int32_t ret;
/* 启动看门狗 */
ret = WatchdogStart(handle);
if (ret != 0) {
HDF_LOGE("WatchdogStart: failed, ret %d\n", ret);
return;
}
```
### 喂狗
int32\_t WatchdogFeed\(DevHandle handle\);
**表 7** WatchdogFeed参数和返回值描述
参数
|
参数描述
|
handle
|
看门狗设备句柄
|
返回值
|
返回值描述
|
0
|
喂狗成功
|
负数
|
喂狗失败
|
```
int32_t ret;
/* 喂狗 */
ret = WatchdogFeed(handle);
if (ret != 0) {
HDF_LOGE("WatchdogFeed: failed, ret %d\n", ret);
return;
}
```
### 停止看门狗
int32\_t WatchdogStop\(DevHandle handle\);
**表 8** WatchdogStop参数和返回值描述
参数
|
参数描述
|
handle
|
看门狗设备句柄
|
返回值
|
返回值描述
|
0
|
停止成功
|
负数
|
停止失败
|
```
int32_t ret;
/* 停止看门狗 */
ret = WatchdogStop(handle);
if (ret != 0) {
HDF_LOGE("WatchdogStop: failed, ret %d\n", ret);
return;
}
```
### 关闭看门狗设备
当操作完毕时,使用WatchdogClose关闭打开的设备句柄:
void WatchdogClose\(DevHandle handle\);
**表 9** WatchdogClose参数和返回值描述
```
/* 关闭看门狗 */
ret = WatchdogClose(handle);
```
## 使用实例
本例程提供看门狗的完整使用流程。
在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时:
- 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。
- 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。
示例如下:
```
#include "watchdog_if.h"
#include "hdf_log.h"
#include "osal_irq.h"
#include "osal_time.h"
#define WATCHDOG_TEST_TIMEOUT 2
#define WATCHDOG_TEST_FEED_TIME 6
static int32_t TestCaseWatchdog(void)
{
int32_t i;
int32_t ret;
uint32_t timeout;
DevHandle handle = NULL;
/* 打开0号看门狗设备 */
handle = WatchdogOpen(0);
if (handle == NULL) {
HDF_LOGE("Open watchdog fail!");
return -1;
}
/* 设置超时时间 */
ret = WatchdogSetTimeout(handle, WATCHDOG_TEST_TIMEOUT);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: set timeout fail! ret:%d\n", __func__, ret);
WatchdogClose(handle);
return ret;
}
/* 回读设置的超时时间值 */
ret = WatchdogGetTimeout(handle, &timeout);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: get timeout fail! ret:%d\n", __func__, ret);
WatchdogClose(handle);
return ret;
}
HDF_LOGI("%s: read timeout back:%u\n", __func__, timeout);
/* 启动看门狗,开始计时 */
ret = WatchdogStart(handle);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: satrt fail! ret:%d\n", __func__, ret);
WatchdogClose(handle);
return ret;
}
/* 每隔1S喂狗一次 */
for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) {
HDF_LOGE("%s: feeding watchdog %d times... \n", __func__, i);
ret = WatchdogFeed(handle);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret);
WatchdogClose(handle);
return ret;
}
OsalSleep(1);
}
/* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */
HDF_LOGE("%s: no reset ... feeding test OK!!!\n", __func__);
/* 接下来持续不喂狗,使得看门狗计时器超时 */
for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) {
HDF_LOGE("%s: watiting dog buck %d times... \n", __func__, i);
OsalSleep(1);
}
/* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */
HDF_LOGE("%s: dog has't buck!!! \n", __func__, i);
WatchdogClose(handle);
return -1;
}
```