1# Watchdog 2 3## Overview 4 5### Function 6 7A watchdog, also called a watchdog timer, is a hardware timing device used to facilitate automatic correction of temporary hardware faults or recover from system malfunctions. Generally, it has an input to feed the watchdog and an output to the reset pin of the system. If an error occurs in the main program of the system and the watchdog timer is not cleared in time, the watchdog timer sends a reset signal to restore the system to the normal state. 8 9The watchdog module provides APIs for watchdog operations, including: 10 11- Opening or closing a watchdog 12- Starting or stopping a watchdog 13- Setting or obtaining the watchdog timeout period 14- Obtaining the watchdog status 15- Feeding a watchdog 16 17### Basic Concepts 18 19When the system works properly, a signal is output to the watchdog to prevent it from timing out. This operation is called watchdog feeding. If the watchdog is not fed within the specified time, the watchdog times out and a reset signal is sent to the system to reset the system. 20 21### Working Principles 22 23In the Hardware Driver Foundation (HDF), the PWM uses the independent service mode (see Figure 1) for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage. 24 25In the independent service mode, the core layer does not publish a service for the upper layer. Therefore, a service must be published for each controller. To achieve this purpose: 26 27- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services. 28- The **policy** field of **deviceNode** in the **device_info.hcs** file can be **1** or **2**, but not **0**. 29 30The watchdog module is divided into the following layers: 31 32- Interface layer: provides APIs for opening or closing a watchdog, starting or stopping a watchdog, setting or obtaining the watchdog timeout period, and feeding a watchdog 33- Core layer: provides the capabilities of adding or removing a watchdog controller and managing watchdog devices. The core layer interacts with the adaptation layer through hook functions. 34- Adaptation layer: instantiates the hook functions to implement specific features. 35 36**Figure 1** Independent service mode 37 38![image1](figures/independent-service-mode.png "Watchdog independent service mode") 39 40## Usage Guidelines 41 42### When to Use 43 44Watchdogs are used to automatically detect the software exceptions that cannot be directly observed and reset the system when an exception is detected. 45 46### Available APIs 47 48The following table describes the APIs provided by the watchdog module. 49 50**Table 1** Watchdog APIs 51 52| API| Description| 53| -------- | -------- | 54| int32_t WatchdogOpen(int16_t wdtId, DevHandle *handle) | Opens a watchdog.| 55| void WatchdogClose(DevHandle handle) | Closes a watchdog.| 56| int32_t WatchdogStart(DevHandle handle) | Starts a watchdog.| 57| int32_t WatchdogStop(DevHandle handle) | Stops a watchdog.| 58| int32_t WatchdogSetTimeout(DevHandle handle, uint32_t seconds) | Sets the watchdog timeout duration.| 59| int32_t WatchdogGetTimeout(DevHandle handle, uint32_t *seconds) | Obtains the watchdog timeout duration.| 60| int32_t WatchdogGetStatus(DevHandle handle, int32_t *status) | Obtains the watchdog status.| 61| int32_t WatchdogFeed(DevHandle handle) | Feeds a watchdog or resets a watchdog timer.| 62 63> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** 64> 65> All watchdog APIs described in this document can be used in kernel mode and user mode. 66 67### How to Develop 68 69The following figure shows how to use the watchdog driver APIs. 70 71**Figure 2** Using watchdog driver APIs 72 73![image2](figures/using-watchdog-process.png) 74 75#### Opening a Watchdog 76 77Before operating a watchdog, you need to use **WatchdogOpen()** to open a watchdog. A system may have multiple watchdogs. You need to specify the ID of the watchdog to open. 78 79```c 80DevHandle WatchdogOpen(int16_t wdtId, DevHandle *handle); 81``` 82 83**Table 2** Description of WatchdogOpen 84 85| **Parameter**| **Description**| 86| -------- | -------- | 87| wdtId | Watchdog ID.| 88| handle | Pointer to the watchdog device handle obtained.| 89| **Return Value**| **Description**| 90| HDF_SUCCESS | The operation is successful.| 91| Negative value| The operation fails.| 92 93```c 94int16_t wdtId = 0; 95int32_t ret; 96DevHandle *handle = NULL; 97 98ret = WatchdogOpen(wdtId, handle); // Open watchdog 0. 99if (ret != HDF_SUCCESS) { 100 HDF_LOGE("WatchdogOpen: open watchdog_%hd failed, ret:%d\n", wdtId, ret); 101 return ret; 102} 103``` 104 105#### Obtaining the Watchdog Status 106 107```c 108int32_t WatchdogGetStatus(DevHandle handle, int32_t *status); 109``` 110 111**Table 3** Description of WatchdogGetStatus 112 113| **Parameter**| **Description**| 114| -------- | -------- | 115| handle | Watchdog device handle.| 116| status | Pointer to the watchdog status obtained.| 117| **Return Value**| **Description**| 118| HDF_SUCCESS | The operation is successful.| 119| Negative value| The operation fails.| 120 121```c 122int32_t ret; 123int32_t status; 124 125ret = WatchdogGetStatus(handle, &status); // Obtain the watchdog status. 126if (ret != HDF_SUCCESS) { 127 HDF_LOGE("WatchdogGetStatus: watchdog get status failed, ret:%d\n", ret); 128 return ret; 129} 130``` 131 132#### Setting the Timeout Duration 133 134 135```c 136int32_t WatchdogSetTimeout(DevHandle *handle, uint32_t seconds); 137``` 138 139**Table 4** Description of WatchdogSetTimeout 140 141| **Parameter**| **Description**| 142| -------- | -------- | 143| handle | Pointer to the watchdog device handle.| 144| seconds | Timeout duration to set, in seconds.| 145| **Return Value**| **Description**| 146| HDF_SUCCESS | The operation is successful.| 147| Negative value| The operation fails.| 148 149```c 150int32_t ret; 151 152ret = WatchdogSetTimeout(handle, 2); // Set the timeout duration to 2 seconds. 153if (ret != HDF_SUCCESS) { 154 HDF_LOGE("WatchdogSetTimeout: watchdog set timeOut failed, ret:%d\n", ret); 155 return ret; 156} 157``` 158 159#### Obtaining the Timeout Duration 160 161```c 162int32_t WatchdogGetTimeout(DevHandle *handle, uint32_t *seconds); 163``` 164 165**Table 5** Description of WatchdogGetTimeout 166 167| **Parameter**| **Description**| 168| -------- | -------- | 169| handle | Pointer to the watchdog device handle.| 170| seconds | Pointer to the watchdog timeout duration obtained.| 171| **Return Value**| **Description**| 172| HDF_SUCCESS | The operation is successful.| 173| Negative value| The operation fails.| 174 175```c 176 int32_t ret; 177 uint32_t timeOut; 178 179 ret = WatchdogGetTimeout(handle, &timeOut); // Obtain the watchdog timeout duration. 180 if (ret != HDF_SUCCESS) { 181 HDF_LOGE("WatchdogGetTimeout: watchdog get timeOut failed, ret:%d\n", ret); 182 return ret; 183 } 184``` 185 186#### Starting a Watchdog 187 188```c 189int32_t WatchdogStart(DevHandle handle); 190``` 191 192**Table 6** Description of WatchdogStart 193 194| **Parameter**| **Description**| 195| -------- | -------- | 196| handle | Watchdog device handle.| 197| **Return Value**| **Description**| 198| HDF_SUCCESS | The operation is successful.| 199| Negative value| The operation fails.| 200 201```c 202int32_t ret; 203 204ret = WatchdogStart(handle); // Start a watchdog. 205if (ret != HDF_SUCCESS) { 206 HDF_LOGE("WatchdogStart: start watchdog failed, ret:%d\n", ret); 207 return ret; 208} 209``` 210 211#### Feeding a Watchdog 212 213```c 214int32_t WatchdogFeed(DevHandle handle); 215``` 216 217**Table 7** Description of WatchdogFeed 218 219| **Parameter**| **Description**| 220| -------- | -------- | 221| handle | Watchdog device handle.| 222| **Return Value**| **Description**| 223| HDF_SUCCESS | The operation is successful.| 224| Negative value| The operation fails.| 225 226```c 227int32_t ret; 228 229ret = WatchdogFeed (handle); // Feed a watchdog. 230if (ret != HDF_SUCCESS) { 231 HDF_LOGE("WatchdogFeed: feed watchdog failed, ret:%d\n", ret); 232 return ret; 233} 234``` 235 236#### Stopping a Watchdog 237 238```c 239int32_t WatchdogStop(DevHandle handle); 240``` 241 242**Table 8** Description of WatchdogStop 243 244| **Parameter**| **Description**| 245| -------- | -------- | 246| handle | Watchdog device handle.| 247| **Return Value**| **Description**| 248| HDF_SUCCESS | The operation is successful.| 249| Negative value| The operation fails.| 250 251```c 252int32_t ret; 253 254ret = WatchdogStop(handle); // Stop a watchdog. 255if (ret != HDF_SUCCESS) { 256 HDF_LOGE("WatchdogStop: stop watchdog failed, ret:%d\n", ret); 257 return ret; 258} 259``` 260 261#### Closing a Watchdog 262 263After all operations are complete, use **WatchdogClose()** to close the watchdog. 264 265```c 266void WatchdogClose(DevHandle handle); 267``` 268 269**Table 9** Description of WatchdogClose 270 271| **Parameter**| **Description**| 272| -------- | -------- | 273| handle | Watchdog device handle.| 274 275```c 276WatchdogClose(handle); // Close a watchdog. 277``` 278 279## Example 280 281The following uses the Hi3516D V300 development board as an example to describe how to operate the watchdog. The procedure is as follows: 282 2831. Open a watchdog. You need to pass in the watchdog ID. The device handle of the watchdog opened is returned. 2842. Set the timeout duration for the watchdog. 2853. Obtain the timeout duration of the watchdog. 2864. Start the watchdog. 2875. Feed the watchdog. 2886. Stop the watchdog. 2897. Close the watchdog. 290 291```c 292#include "watchdog_if.h" /* Header file of the standard watchdog APIs. */ 293#include "hdf_log.h" /* Header file of the HDF log APIs. */ 294#include "osal_time.h" /* Header file of the delay and sleep APIs. */ 295 296#define WATCHDOG_TEST_TIMEOUT 2 297#define WATCHDOG_TEST_FEED_TIME 6 298 299static int32_t TestCaseWatchdog(void) 300{ 301 int32_t i; 302 int32_t ret; 303 int16_t wdtId = 0; 304 int32_t status; 305 uint32_t timeout; 306 DevHandle *handle = NULL; 307 308 /* Open watchdog 0. */ 309 ret = WatchdogOpen(wdtId, handle); 310 if (ret != HDF_SUCCESS) { 311 HDF_LOGE("WatchdogOpen: open watchdog_%hd failed, ret:%d\n", wdtId, ret); 312 return ret; 313 } 314 315 /* Set the timeout duration. */ 316 ret = WatchdogSetTimeout(handle, WATCHDOG_TEST_TIMEOUT); 317 if (ret != HDF_SUCCESS) { 318 HDF_LOGE("%s: set timeout fail! ret:%d\n", __func__, ret); 319 WatchdogClose(handle); 320 return ret; 321 } 322 323 /* Obtain the timeout duration. */ 324 ret = WatchdogGetTimeout(handle, &timeout); 325 if (ret != HDF_SUCCESS) { 326 HDF_LOGE("%s: get timeout fail! ret:%d\n", __func__, ret); 327 WatchdogClose(handle); 328 return ret; 329 } 330 /* Check whether the timeout duration obtained is the same as the timeout duration set. */ 331 if (timeout != WATCHDOG_TEST_TIMEOUT) { 332 HDF_LOGE("%s: set:%u, but get:%u", __func__, WATCHDOG_TEST_TIMEOUT, timeout); 333 WatchdogClose(handle); 334 return HDF_FAILURE; 335 } 336 HDF_LOGI("%s: read timeout back:%u\n", __func__, timeout); 337 338 /* Start the watchdog. The timer starts. */ 339 ret = WatchdogStart(handle); 340 if (ret != HDF_SUCCESS) { 341 HDF_LOGE("%s: start fail! ret:%d\n", __func__, ret); 342 WatchdogClose(handle); 343 return ret; 344 } 345 /* Obtain the watchdog status and determine whether to start the watchdog. */ 346 status = WATCHDOG_STOP; 347 ret = WatchdogGetStatus(handle, &status); 348 if (ret != HDF_SUCCESS) { 349 HDF_LOGE("%s: get status fail! ret:%d", __func__, ret); 350 WatchdogClose(handle); 351 return ret; 352 } 353 if (status != WATCHDOG_START) { 354 HDF_LOGE("%s: status is:%d after start", __func__, status); 355 WatchdogClose(handle); 356 return HDF_FAILURE; 357 } 358 359 /* Feed the watchdog every other second. */ 360 for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { 361 HDF_LOGI("%s: feeding watchdog %d times... \n", __func__, i); 362 ret = WatchdogFeed(handle); 363 if (ret != HDF_SUCCESS) { 364 HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret); 365 WatchdogClose(handle); 366 return ret; 367 } 368 OsalSleep(1); 369 } 370 /* Because the interval for feeding the watchdog is shorter than the timeout duration, the system does not reset, and logs can be printed normally. */ 371 HDF_LOGI("%s: no reset ... feeding test OK!!!\n", __func__); 372 373 ret = WatchdogStop(handle); 374 if (ret != HDF_SUCCESS) { 375 HDF_LOGE("%s: stop fail! ret:%d", __func__, ret); 376 WatchdogClose(handle); 377 return ret; 378 } 379 /* Obtain the watchdog status and determine whether to close the watchdog. */ 380 status = WATCHDOG_START; 381 ret = WatchdogGetStatus(handle, &status); 382 if (ret != HDF_SUCCESS) { 383 HDF_LOGE("%s: get status fail! ret:%d", __func__, ret); 384 WatchdogClose(handle); 385 return ret; 386 } 387 if (status != WATCHDOG_STOP) { 388 HDF_LOGE("%s: status is:%d after stop", __func__, status); 389 WatchdogClose(handle); 390 return HDF_FAILURE; 391 } 392 WatchdogClose(handle); 393 return HDF_SUCCESS; 394} 395``` 396