• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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