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 9### Basic Concepts 10 11When 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. 12 13### Working Principles 14 15In the Hardware Driver Foundation (HDF), the watchdog module 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. 16 17In 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: 18 19- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services. 20- The **policy** field of **deviceNode** in the **device_info.hcs** file can be **1** or **2**, but not **0**. 21 22The watchdog module is divided into the following layers: 23 24- 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 25- 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. 26- Adaptation layer: instantiates the hook functions to implement specific features. 27 28**Figure 1** Independent service mode 29 30![image](figures/independent-service-mode.png "Watchdog independent service mode") 31 32## Development Guidelines 33 34### When to Use 35 36Watchdogs are used to automatically detect the software exceptions that cannot be directly observed and reset the system when an exception is detected. Before using your watchdogs with OpenHarmony, you need to perform watchdog driver adaptation. The following describes how to do it. 37 38### **Available APIs** 39 40To enable the upper layer to successfully operate the watchdog controller by calling the watchdog APIs, hook functions are defined in **//drivers/hdf_core/framework/support/platform/include/watchdog/watchdog_core.h** for the core layer. You need to implement these hook functions at the adaptation layer and hook them to implement the interaction between the interface layer and the core layer. 41 42**WatchdogMethod**: 43 44```c 45struct WatchdogMethod { 46 int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status); 47 int32_t (*setTimeout)(struct WatchdogCntlr *wdt, uint32_t seconds); 48 int32_t (*getTimeout)(struct WatchdogCntlr *wdt, uint32_t *seconds); 49 int32_t (*start)(struct WatchdogCntlr *wdt); 50 int32_t (*stop)(struct WatchdogCntlr *wdt); 51 int32_t (*feed)(struct WatchdogCntlr *wdt); 52 int32_t (*getPriv)(struct WatchdogCntlr *wdt); // (Optional) If WatchdogCntlr has the priv member, instantiate priv. 53 void (*releasePriv)(struct WatchdogCntlr *wdt); // (Optional) 54}; 55``` 56 57**Table 1** Hook functions in WatchdogMethod 58 59| Function| Input Parameter| Output Parameter| Return Value| Description| 60| -------- | -------- | -------- | -------- | -------- | 61| getStatus | **wdt**: structure pointer to the watchdog controller at the core layer.| status: pointer to the watchdog status (opened or closed) obtained. The value is of the int32_t type.| HDF_STATUS| Obtains the watchdog status.| 62| setTimeout | **wdt**: structure pointer to the watchdog controller at the core layer.<br>**seconds**: watchdog timeout duration to set.| –| HDF_STATUS| Sets the watchdog timeout duration, in seconds. Ensure that the actual running time of the watchdog complies with the value set.| 63| getTimeout | **wdt**: structure pointer to the watchdog controller at the core layer. | **seconds**: pointer to the timeout duration obtained. The value is of the uint32_t type. | HDF_STATUS| Obtains the watchdog timeout duration. | 64| start | **wdt**: structure pointer to the watchdog controller at the core layer. | – | HDF_STATUS| Starts a watchdog. | 65| stop | **wdt**: structure pointer to the watchdog controller at the core layer. | – | HDF_STATUS| Stops a watchdog. | 66| feed | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Feeds a watchdog. | 67| getPriv | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Obtains the private data of the watchdog driver.| 68| releasePriv | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Releases the private data of the watchdog driver.| 69 70### How to Develop 71 72The watchdog module adaptation procedure is as follows: 73 741. Instantiate the driver entry. 752. Configure attribute files. 763. Instantiate the watchdog controller object. 774. Debug the driver. 78 79### Example 80 81The following uses the **//device_soc_hisilicon/common/platform/watchdog/watchdog_hi35xx.c** driver of the Hi3516D V300 development board as an example to describe the watchdog driver adaptation. 82 831. Instantiate the driver entry. 84 85 The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF framework, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke. 86 Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. 87 88 Watchdog driver entry example: 89 90 ```c 91 struct HdfDriverEntry g_watchdogDriverEntry = { 92 .moduleVersion = 1, 93 .Bind = Hi35xxWatchdogBind, // See the Bind function. 94 .Init = Hi35xxWatchdogInit, // See the Init function. 95 .Release = Hi35xxWatchdogRelease, // See the Release function. 96 .moduleName = "HDF_PLATFORM_WATCHDOG", // (Mandatory) The value must be the same as that of moduleName in the .hcs file. 97 }; 98 HDF_INIT(g_watchdogDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. 99 ``` 100 1012. Configure attribute files. 102 103 Add the deviceNode information to the **device_info.hcs** file. The deviceNode information is related to the driver entry registration. The following example uses one watchdog controller as an example. If there are more watchdog controllers, add the deviceNode information to the **device_info.hcs** file for each controller. The device attribute values configured in **watchdog_config.hcs** are closely related to default values or value ranges of the **WatchdogCntlr** members at the core layer. 104 105 - **device_info.hcs** example: 106 107 Add the deviceNode information to the **//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file. 108 109 ```c 110 root { 111 device_info { 112 match_attr = "hdf_manager"; 113 device_watchdog :: device { // Device node. 114 device0 :: deviceNode { // DeviceNode of the driver. 115 policy = 2; // The value 2 means to publish services for both kernel- and user-mode processes. 116 priority = 20; // Driver startup priority. 117 permission = 0644; // Permission for the device node created. 118 moduleName = "HDF_PLATFORM_WATCHDOG"; // (Mandatory) Driver name, which must be the same as that of moduleName in the driver entry structure. 119 serviceName = "HDF_PLATFORM_WATCHDOG_0"; // (Mandatory) Unique name of the service released by the driver. 120 deviceMatchAttr = "hisilicon_hi35xx_watchdog_0"; // (Mandatory) Controller private data, which must be the same as the value of match_attr in watchdog_config.hcs. 121 } 122 } 123 } 124 } 125 ``` 126 127 - **watchdog_config.hcs** example: 128 129 Configure the device attributes in the **//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/watchdog/watchdog_config.hcs** file. The parameters are as follows: 130 131 ```c 132 root { 133 platform { 134 template watchdog_controller { // (Mandatory) Template configuration. If the template is used to configure device node information, the default values in the template will be used for the fields that are not declared for the node. 135 id = 0; // Watchdog ID. 136 match_attr = ""; 137 regBase = 0x12050000; // (Mandatory) Physical base address used for address mapping. 138 regStep = 0x1000; // (Mandatory) Register offset step used for address mapping. 139 } 140 controller_0x12050000 :: watchdog_controller { // (Mandatory) Keyword for matching the private data of the device driver. 141 match_attr = "hisilicon_hi35xx_watchdog_0"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs. 142 } 143 // Add node information for each watchdog device. 144 ... 145 } 146 } 147 ``` 148 149 After the **watchdog_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect. 150 151 ```c 152 #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/watchdog/watchdog_config.hcs" // Relative path of the file. 153 ``` 154 1553. Instantiate the watchdog controller object. 156 157 Initialize the **WatchdogCntlr** object at the core layer, including defining a custom structure (to pass parameters and data) and implementing the **HdfDriverEntry** member functions (**Bind**, **Init** and **Release**) to instantiate **WatchdogMethod** in **WatchdogCntlr** (so that the underlying driver functions can be called). 158 159 - Define a custom structure. 160 161 To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **watchdog_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the watchdog ID, to the object at the core layer. 162 163 ```c 164 struct Hi35xxWatchdog { 165 struct WatchdogCntlr wdt; // (Mandatory) Control object of the core layer. For details, see the following description. 166 OsalSpinlock lock; // (Mandatory) You need to implement the spinlock for your watchdog. 167 volatile unsigned char *regBase; // (Mandatory) Register base address used for address mapping. 168 uint32_t phyBase; // (Mandatory) Physical base address used for address mapping. 169 uint32_t regStep; // (Mandatory) Register offset step used for address mapping. 170 }; 171 172 struct WatchdogCntlr { // WatchdogCntlr is the controller structure at the core layer. The Init function assigns values to WatchdogCntlr. 173 struct IDeviceIoService service; // Driver service. 174 struct HdfDeviceObject *device; // Driver device object. 175 OsalSpinlock lock; // Spinlock. 176 struct WatchdogMethod *ops; // Hook functions. 177 int16_t wdtId; // Watchdog ID. 178 void *priv; // Private data. 179 }; 180 ``` 181 182 - Instantiate **WatchdogMethod** in **WatchdogCntlr**. 183 184 ```c 185 static struct WatchdogMethod g_method = { // Instantiate the hook functions. 186 .getStatus = Hi35xxWatchdogGetStatus, // Obtain the watchdog status. 187 .start = Hi35xxWatchdogStart, // Start the watchdog. 188 .stop = Hi35xxWatchdogStop, // Stop the watchdog. 189 .setTimeout = Hi35xxWatchdogSetTimeout, // Set the watchdog timeout duration. 190 .getTimeout = Hi35xxWatchdogGetTimeout, //Obtain the watchdog timeout duration. 191 .feed = Hi35xxWatchdogFeed, // Feed the watchdog. 192 }; 193 ``` 194 195 - Implement the **Init** and **Bind** functions. 196 197 Input parameter: 198 199 **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 200 201 Return value: 202 203 **HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **//drivers/hdf_core/framework/include/utils/hdf_base.h** file. 204 205 **Table 2** Description of HDF_STATUS 206 207 | Status| Description| 208 | -------- | -------- | 209 | HDF_ERR_INVALID_OBJECT | Invalid controller object.| 210 | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.| 211 | HDF_ERR_IO | I/O error.| 212 | HDF_SUCCESS | Initialization successful.| 213 | HDF_FAILURE | Initialization failed.| 214 215 Function description: 216 217 Initializes the custom structure object and **WatchdogCntlr**, and calls **WatchdogCntlrAdd()** at the core layer to add the watchdog controller. 218 219 ```c 220 // Generally, the Init function initializes the members of the Hi35xxWatchdog structure based on the attribute values in **HdfDeviceObject**. 221 // In watchdog_hi35xx.c, it is implemented by the Bind function. 222 static int32_t Hi35xxWatchdogInit(struct HdfDeviceObject *device) 223 { 224 (void)device; 225 return HDF_SUCCESS; 226 } 227 228 static int32_t Hi35xxWatchdogBind(struct HdfDeviceObject *device) 229 { 230 int32_t ret; 231 struct Hi35xxWatchdog *hwdt = NULL; 232 ... 233 hwdt = (struct Hi35xxWatchdog *)OsalMemCalloc(sizeof(*hwdt)); // Allocate memory for the Hi35xxWatchdog structure pointer. 234 ... 235 hwdt->regBase = OsalIoRemap(hwdt->phyBase, hwdt->regStep); // Address mapping. 236 ... 237 hwdt->wdt.priv = (void *)device->property; // (Mandatory) Use the device attributes to assign values to privr, but priv is not called later. 238 //If the priv member is required, instantiate getPriv() and releasePriv() of WatchdogMethod. 239 hwdt->wdt.ops = &g_method; // (Mandatory) Hook the WatchdogMethod instance. 240 hwdt->wdt.device = device; // (Mandatory) Enable conversion between HdfDeviceObject and WatchdogcCntlr. 241 ret = WatchdogCntlrAdd(&hwdt->wdt); // (Mandatory) Call this function to initialize the core layer structure. The driver can access the platform core layer only after a success signal is returned. 242 if (ret != HDF_SUCCESS) { // If the operation fails, remove the mapping and release the resources requested by the Init function. 243 OsalIoUnmap((void *)hwdt->regBase); 244 OsalMemFree(hwdt); 245 return ret; 246 } 247 return HDF_SUCCESS; 248 } 249 ``` 250 251 - Implement the **Release** function. 252 253 Input parameter: 254 255 **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 256 257 Return value: 258 259 No value is returned. 260 261 Function description: 262 263 Releases driver resources. This function assigns values to **Release()** in the driver entry structure. When the HDF fails to call **Init()** to initialize the driver, **Release()** is called to release driver resources. The **Release()** function must contain the operations for releasing the memory and deleting the controller. 264 265 ```c 266 static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) 267 { 268 struct WatchdogCntlr *wdt = NULL; 269 struct Hi35xxWatchdog *hwdt = NULL; 270 ... 271 wdt = WatchdogCntlrFromDevice(device); // (Mandatory) Obtain WatchdogCntlr through device. 272 ... 273 if (wdt == NULL) { 274 return; 275 } 276 WatchdogCntlrRemove(wdt); // (Mandatory) Call WatchdogCntlrRemove to release the WatchdogCntlr object. 277 hwdt = (struct Hi35xxWatchdog *)wdt; // Convert WatchdogCntlr to Hi35xxWatchdog. 278 if (hwdt->regBase != NULL) { // (Mandatory) Remove the address mapping. 279 OsalIoUnmap((void *)hwdt->regBase); 280 hwdt->regBase = NULL; 281 } 282 OsalMemFree(hwdt); // (Mandatory) Release the memory occupied by the custom object. 283 } 284 ``` 285 2864. Debug the driver. 287 288 (Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether data is successfully transmitted. 289