1# Watchdog 2 3 4## **Overview** 5 6A 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. 7 8In the Hardware Driver Foundation (HDF), the watchdog uses the independent service mode 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. 9 10 **Figure 1** Independent service mode 11 12  13 14 15## **Available APIs** 16 17**WatchdogMethod**: 18 19 20``` 21struct WatchdogMethod { 22 int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status); 23 int32_t (*setTimeout)(struct WatchdogCntlr *wdt, uint32_t seconds); 24 int32_t (*getTimeout)(struct WatchdogCntlr *wdt, uint32_t *seconds); 25 int32_t (*start)(struct WatchdogCntlr *wdt); 26 int32_t (*stop)(struct WatchdogCntlr *wdt); 27 int32_t (*feed)(struct WatchdogCntlr *wdt); 28 int32_t (*getPriv)(struct WatchdogCntlr *wdt); // (Optional) If WatchdogCntlr has the priv member, instantiate priv. 29 void (*releasePriv)(struct WatchdogCntlr *wdt);// (Optional) 30}; 31``` 32 33 **Table 1** Description of the callback functions in WatchdogMethod 34 35| Function| Input Parameter| Output Parameter| Return Value| Description| 36| -------- | -------- | -------- | -------- | -------- | 37| getStatus | **wdt**: structure pointer to the watchdog controller at the core layer.| **status**: int32_t pointer to the watchdog status (started or stopped).| HDF_STATUS| Obtains the watchdog status.| 38| start | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Starts a watchdog.| 39| stop | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS | Stops a watchdog.| 40| setTimeout | **wdt**: structure pointer to the watchdog controller at the core layer.<br/>**seconds**: Timeout duration to set, in seconds. The value is of the uint32_t type. | – | HDF_STATUS | Sets the timeout duration for a watchdog. | 41| getTimeout | **wdt**: structure pointer to the watchdog controller at the core layer.| **seconds**: Pointer to the watchdog timeout duration obtained. The value is of the uint32_t type. | HDF_STATUS| Obtains the timeout duration of a watchdog.| 42| feed | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Feeds a watchdog. | 43 44 45## How to Develop 46 47The watchdog module adaptation involves the following steps: 48 491. Instantiate the driver entry. 50 - Instantiate the **HdfDriverEntry** structure. 51 - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF. 52 532. Configure attribute files. 54 - Add the **deviceNode** information to the **device_info.hcs** file. 55 - (Optional) Add the **watchdog_config.hcs** file. 56 573. Instantiate the watchdog controller object. 58 - Initialize **WatchdogCntlr**. 59 - Instantiate **WatchdogMethod** in the **WatchdogCntlr** object. 60 61 >  **NOTE** 62 > 63 > For details about the functions in **WatchdogMethod**, see [Available APIs](#available-apis). 64 654. Debug the driver. 66 67 (Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether the watchdog timer is successfully set. 68 69 70## Development Example 71 72The following uses **watchdog_hi35xx.c** as an example to present the information required for implementing device functions. 73 741. Instantiate the driver entry. 75 76 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, 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. 77 78 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. 79 80 Watchdog driver entry example: 81 82 ``` 83 struct HdfDriverEntry g_watchdogDriverEntry = { 84 .moduleVersion = 1, 85 .Bind = Hi35xxWatchdogBind, // See the Bind function. 86 .Init = Hi35xxWatchdogInit, // See the Init function. 87 .Release = Hi35xxWatchdogRelease, // See the Release function. 88 .moduleName = "HDF_PLATFORM_WATCHDOG",// (Mandatory) The value must be the same as that of moduleName in the .hcs file. 89 }; 90 HDF_INIT(g_watchdogDriverEntry);// Call HDF_INIT to register the driver entry with the HDF. 91 ``` 92 932. Add the **deviceNode** information to the **device_info.hcs** file and configure the component attributes in the **watchdog_config.hcs** file. 94 95 The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **WatchdogCntlr** members at the core layer. 96 97 In this example, there is only one watchdog controller. If there are multiple watchdog controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **watchdog_config** file for each controller. 98 99 - **device_info.hcs** configuration example: 100 101 102 ``` 103 root { 104 device_info { 105 match_attr = "hdf_manager"; 106 device_watchdog :: device {// Device node. 107 device0:: deviceNode { // Device node of the driver. 108 policy = 1; // Policy for the driver to provide services. 109 priority = 20; // Driver startup priority. 110 permission = 0644; // Permission to create device nodes for the driver. 111 moduleName = "HDF_PLATFORM_WATCHDOG"; 112 // (Mandatory) Driver name. The value must be the same as that of moduleName in the driver entry structure. 113 serviceName = "HDF_PLATFORM_WATCHDOG_0"; 114 // (Mandatory) Unique name of the service published by the driver. 115 deviceMatchAttr = "hisilicon_hi35xx_watchdog_0"; 116 // (Mandatory) Keyword matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver. 117 } 118 } 119 } 120 } 121 ``` 122 123 - **watchdog_config.hcs** configuration example: 124 125 126 ``` 127 root { 128 platform { 129 template watchdog_controller {// (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes. 130 id = 0; 131 match_attr = ""; 132 regBase = 0x12050000; // (Mandatory) Used for address mapping. 133 regStep = 0x1000; // (Mandatory) Used for address mapping. 134 } 135 controller_0x12050000 :: watchdog_controller {// (Mandatory) Keyword for matching the private data of the device driver. 136 match_attr = "hisilicon_hi35xx_watchdog_0"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs. 137 } 138 // Configure this parameter when there are multiple watchdogs. 139 ... 140 } 141 } 142 ``` 143 1443. 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). 145 - Defining a custom structure 146 147 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 index and the number of pins, to the **WatchdogCntlr** object at the core layer. 148 149 150 ``` 151 struct Hi35xxWatchdog { 152 struct WatchdogCntlr wdt; // (Mandatory) Carrier that connects the upper and underlying layers. For details, see the following description. 153 OsalSpinlock lock; 154 volatile unsigned char *regBase;// [Mandatory] Used for address mapping. 155 uint32_t phyBase; // (Mandatory) Used for address mapping. 156 uint32_t regStep; // (Mandatory) Used for address mapping. 157 }; 158 // WatchdogCntlr is the core layer controller structure. The Init function assigns values to the members of WatchdogCntlr. 159 struct WatchdogCntlr { 160 struct IDeviceIoService service;// Driver service. 161 struct HdfDeviceObject *device; // Driver device. 162 OsalSpinlock lock; // This variable is called by the HDF core layer to implement the spinlock function. 163 struct WatchdogMethod *ops; // Callbacks. 164 int16_t wdtId // ID of the watchdog device. 165 void *priv; // Pointer to the driver's private data. 166 }; 167 ``` 168 169 - Instantiating **WatchdogMethod** in **WatchdogCntlr** (other members are initialized by **Init** and **Bind**) 170 171 172 ``` 173 static struct WatchdogMethod g_method = { 174 .getStatus = Hi35xxWatchdogGetStatus, 175 .start = Hi35xxWatchdogStart, 176 .stop = Hi35xxWatchdogStop, 177 .setTimeout = Hi35xxWatchdogSetTimeout, 178 .getTimeout = Hi35xxWatchdogGetTimeout, 179 .feed = Hi35xxWatchdogFeed, 180 }; 181 ``` 182 183 - **Init** and **Bind** functions 184 185 Input parameter: 186 187 **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 188 189 Return value: 190 191 HDF_STATUS 192 193 The table below lists some status. For more information, see **HDF_STATUS** in the /drivers/framework/include/utils/hdf_base.h file. 194 195 **Table 2** HDF_STATUS 196 197 | Status| Description| 198 | -------- | -------- | 199 | HDF_ERR_INVALID_OBJECT | Failed to locate the watchdog device.| 200 | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.| 201 | HDF_ERR_IO | I/O error.| 202 | HDF_SUCCESS | Initialization successful.| 203 | HDF_FAILURE | Initialization failed.| 204 205 Function description: 206 207 Initializes the custom structure object and **WatchdogCntlr**, and calls the **WatchdogCntlrAdd** function at the core layer. 208 209 210 ``` 211 // Generally, the Init function initializes the members of the Hi35xxWatchdog structure based on the attribute values in **HdfDeviceObject**. 212 // In this example, the Bind function initializes the Hi35xxWatchdog structure. 213 static int32_t Hi35xxWatchdogInit(struct HdfDeviceObject *device) 214 { 215 (void)device; 216 return HDF_SUCCESS; 217 } 218 219 static int32_t Hi35xxWatchdogBind(struct HdfDeviceObject *device) 220 { 221 int32_t ret; 222 struct Hi35xxWatchdog *hwdt = NULL; 223 ... 224 hwdt = (struct Hi35xxWatchdog *)OsalMemCalloc(sizeof(*hwdt));// Apply for memory for the Hi35xxWatchdog structure. 225 ... 226 hwdt->regBase = OsalIoRemap(hwdt->phyBase, hwdt->regStep); // Address mapping 227 ... 228 hwdt->wdt.priv = (void *)device->property;// (Optional) Assign the device attribute values to priv. However, priv is not called subsequently. 229 //If the priv member is required, instantiate getPriv() and releasePriv() of WatchdogMethod. 230 hwdt->wdt.ops = &g_method; // (Mandatory) Assign the instantiated objects to the ops members so that the top layer can invoke the WatchdogMethod functions. 231 hwdt->wdt.device = device; // (Mandatory) Enable conversion between HdfDeviceObject and WatchdogcCntlr. 232 ret = WatchdogCntlrAdd(&hwdt->wdt); // (Mandatory) Call this function to initialize the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned. 233 if (ret != HDF_SUCCESS) { // If the operation fails, release the resources used by Init(). 234 OsalIoUnmap((void *)hwdt->regBase); 235 OsalMemFree(hwdt); 236 return ret; 237 } 238 return HDF_SUCCESS; 239 } 240 ``` 241 242 - **Release** function 243 244 Input parameter: 245 246 **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 247 248 Return value: 249 250 No value is returned. 251 252 Function description: 253 254 Releases driver resources. This function assigns values to **Release()** in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, **Release()** can be called to release driver resources. The **Release()** function must contain the operations for releasing the memory and deleting the controller. 255 256 All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations. 257 258 259 ``` 260 static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) 261 { 262 struct WatchdogCntlr *wdt = NULL; 263 struct Hi35xxWatchdog *hwdt = NULL; 264 ... 265 wdt = WatchdogCntlrFromDevice(device);// Use service to convert HdfDeviceObject to WatchdogCntlr. 266 // return (device == NULL) ? NULL : (struct WatchdogCntlr *)device->service; 267 if (wdt == NULL) { 268 return; 269 } 270 WatchdogCntlrRemove(wdt); // Core layer function used to execute wdt->device->service = NULL and release cntlr->lock. 271 hwdt = (struct Hi35xxWatchdog *)wdt; // Convert WatchdogCntlr to HimciHost. 272 if (hwdt->regBase != NULL) { // Unmap addresses. 273 OsalIoUnmap((void *)hwdt->regBase); 274 hwdt->regBase = NULL; 275 } 276 OsalMemFree(hwdt); // Release the memory occupied by the vendor-defined objects. 277 } 278 ``` 279