1e41f4b71Sopenharmony_ci# Watchdog 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Function 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciA 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. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci### Basic Concepts 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ciWhen 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. 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci### Working Principles 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ciIn 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. 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ciIn 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: 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci- You need to implement the **Bind()** function in **HdfDriverEntry** to bind services. 20e41f4b71Sopenharmony_ci- The **policy** field of **deviceNode** in the **device_info.hcs** file can be **1** or **2**, but not **0**. 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ciThe watchdog module is divided into the following layers: 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci- 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 25e41f4b71Sopenharmony_ci- 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. 26e41f4b71Sopenharmony_ci- Adaptation layer: instantiates the hook functions to implement specific features. 27e41f4b71Sopenharmony_ci 28e41f4b71Sopenharmony_ci**Figure 1** Independent service mode 29e41f4b71Sopenharmony_ci 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci## Development Guidelines 33e41f4b71Sopenharmony_ci 34e41f4b71Sopenharmony_ci### When to Use 35e41f4b71Sopenharmony_ci 36e41f4b71Sopenharmony_ciWatchdogs 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. 37e41f4b71Sopenharmony_ci 38e41f4b71Sopenharmony_ci### **Available APIs** 39e41f4b71Sopenharmony_ci 40e41f4b71Sopenharmony_ciTo 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. 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci**WatchdogMethod**: 43e41f4b71Sopenharmony_ci 44e41f4b71Sopenharmony_ci```c 45e41f4b71Sopenharmony_cistruct WatchdogMethod { 46e41f4b71Sopenharmony_ci int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status); 47e41f4b71Sopenharmony_ci int32_t (*setTimeout)(struct WatchdogCntlr *wdt, uint32_t seconds); 48e41f4b71Sopenharmony_ci int32_t (*getTimeout)(struct WatchdogCntlr *wdt, uint32_t *seconds); 49e41f4b71Sopenharmony_ci int32_t (*start)(struct WatchdogCntlr *wdt); 50e41f4b71Sopenharmony_ci int32_t (*stop)(struct WatchdogCntlr *wdt); 51e41f4b71Sopenharmony_ci int32_t (*feed)(struct WatchdogCntlr *wdt); 52e41f4b71Sopenharmony_ci int32_t (*getPriv)(struct WatchdogCntlr *wdt); // (Optional) If WatchdogCntlr has the priv member, instantiate priv. 53e41f4b71Sopenharmony_ci void (*releasePriv)(struct WatchdogCntlr *wdt); // (Optional) 54e41f4b71Sopenharmony_ci}; 55e41f4b71Sopenharmony_ci``` 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci**Table 1** Hook functions in WatchdogMethod 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci| Function| Input Parameter| Output Parameter| Return Value| Description| 60e41f4b71Sopenharmony_ci| -------- | -------- | -------- | -------- | -------- | 61e41f4b71Sopenharmony_ci| 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.| 62e41f4b71Sopenharmony_ci| 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.| 63e41f4b71Sopenharmony_ci| 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. | 64e41f4b71Sopenharmony_ci| start | **wdt**: structure pointer to the watchdog controller at the core layer. | – | HDF_STATUS| Starts a watchdog. | 65e41f4b71Sopenharmony_ci| stop | **wdt**: structure pointer to the watchdog controller at the core layer. | – | HDF_STATUS| Stops a watchdog. | 66e41f4b71Sopenharmony_ci| feed | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Feeds a watchdog. | 67e41f4b71Sopenharmony_ci| getPriv | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Obtains the private data of the watchdog driver.| 68e41f4b71Sopenharmony_ci| releasePriv | **wdt**: structure pointer to the watchdog controller at the core layer.| –| HDF_STATUS| Releases the private data of the watchdog driver.| 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci### How to Develop 71e41f4b71Sopenharmony_ci 72e41f4b71Sopenharmony_ciThe watchdog module adaptation procedure is as follows: 73e41f4b71Sopenharmony_ci 74e41f4b71Sopenharmony_ci1. Instantiate the driver entry. 75e41f4b71Sopenharmony_ci2. Configure attribute files. 76e41f4b71Sopenharmony_ci3. Instantiate the watchdog controller object. 77e41f4b71Sopenharmony_ci4. Debug the driver. 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ci### Example 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ciThe 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. 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci1. Instantiate the driver entry. 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci 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. 86e41f4b71Sopenharmony_ci 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. 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci Watchdog driver entry example: 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci ```c 91e41f4b71Sopenharmony_ci struct HdfDriverEntry g_watchdogDriverEntry = { 92e41f4b71Sopenharmony_ci .moduleVersion = 1, 93e41f4b71Sopenharmony_ci .Bind = Hi35xxWatchdogBind, // See the Bind function. 94e41f4b71Sopenharmony_ci .Init = Hi35xxWatchdogInit, // See the Init function. 95e41f4b71Sopenharmony_ci .Release = Hi35xxWatchdogRelease, // See the Release function. 96e41f4b71Sopenharmony_ci .moduleName = "HDF_PLATFORM_WATCHDOG", // (Mandatory) The value must be the same as that of moduleName in the .hcs file. 97e41f4b71Sopenharmony_ci }; 98e41f4b71Sopenharmony_ci HDF_INIT(g_watchdogDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. 99e41f4b71Sopenharmony_ci ``` 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci2. Configure attribute files. 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ci 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. 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci - **device_info.hcs** example: 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci Add the deviceNode information to the **//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file. 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci ```c 110e41f4b71Sopenharmony_ci root { 111e41f4b71Sopenharmony_ci device_info { 112e41f4b71Sopenharmony_ci match_attr = "hdf_manager"; 113e41f4b71Sopenharmony_ci device_watchdog :: device { // Device node. 114e41f4b71Sopenharmony_ci device0 :: deviceNode { // DeviceNode of the driver. 115e41f4b71Sopenharmony_ci policy = 2; // The value 2 means to publish services for both kernel- and user-mode processes. 116e41f4b71Sopenharmony_ci priority = 20; // Driver startup priority. 117e41f4b71Sopenharmony_ci permission = 0644; // Permission for the device node created. 118e41f4b71Sopenharmony_ci moduleName = "HDF_PLATFORM_WATCHDOG"; // (Mandatory) Driver name, which must be the same as that of moduleName in the driver entry structure. 119e41f4b71Sopenharmony_ci serviceName = "HDF_PLATFORM_WATCHDOG_0"; // (Mandatory) Unique name of the service released by the driver. 120e41f4b71Sopenharmony_ci deviceMatchAttr = "hisilicon_hi35xx_watchdog_0"; // (Mandatory) Controller private data, which must be the same as the value of match_attr in watchdog_config.hcs. 121e41f4b71Sopenharmony_ci } 122e41f4b71Sopenharmony_ci } 123e41f4b71Sopenharmony_ci } 124e41f4b71Sopenharmony_ci } 125e41f4b71Sopenharmony_ci ``` 126e41f4b71Sopenharmony_ci 127e41f4b71Sopenharmony_ci - **watchdog_config.hcs** example: 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci Configure the device attributes in the **//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/watchdog/watchdog_config.hcs** file. The parameters are as follows: 130e41f4b71Sopenharmony_ci 131e41f4b71Sopenharmony_ci ```c 132e41f4b71Sopenharmony_ci root { 133e41f4b71Sopenharmony_ci platform { 134e41f4b71Sopenharmony_ci 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. 135e41f4b71Sopenharmony_ci id = 0; // Watchdog ID. 136e41f4b71Sopenharmony_ci match_attr = ""; 137e41f4b71Sopenharmony_ci regBase = 0x12050000; // (Mandatory) Physical base address used for address mapping. 138e41f4b71Sopenharmony_ci regStep = 0x1000; // (Mandatory) Register offset step used for address mapping. 139e41f4b71Sopenharmony_ci } 140e41f4b71Sopenharmony_ci controller_0x12050000 :: watchdog_controller { // (Mandatory) Keyword for matching the private data of the device driver. 141e41f4b71Sopenharmony_ci match_attr = "hisilicon_hi35xx_watchdog_0"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs. 142e41f4b71Sopenharmony_ci } 143e41f4b71Sopenharmony_ci // Add node information for each watchdog device. 144e41f4b71Sopenharmony_ci ... 145e41f4b71Sopenharmony_ci } 146e41f4b71Sopenharmony_ci } 147e41f4b71Sopenharmony_ci ``` 148e41f4b71Sopenharmony_ci 149e41f4b71Sopenharmony_ci After the **watchdog_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect. 150e41f4b71Sopenharmony_ci 151e41f4b71Sopenharmony_ci ```c 152e41f4b71Sopenharmony_ci #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/watchdog/watchdog_config.hcs" // Relative path of the file. 153e41f4b71Sopenharmony_ci ``` 154e41f4b71Sopenharmony_ci 155e41f4b71Sopenharmony_ci3. Instantiate the watchdog controller object. 156e41f4b71Sopenharmony_ci 157e41f4b71Sopenharmony_ci 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). 158e41f4b71Sopenharmony_ci 159e41f4b71Sopenharmony_ci - Define a custom structure. 160e41f4b71Sopenharmony_ci 161e41f4b71Sopenharmony_ci 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. 162e41f4b71Sopenharmony_ci 163e41f4b71Sopenharmony_ci ```c 164e41f4b71Sopenharmony_ci struct Hi35xxWatchdog { 165e41f4b71Sopenharmony_ci struct WatchdogCntlr wdt; // (Mandatory) Control object of the core layer. For details, see the following description. 166e41f4b71Sopenharmony_ci OsalSpinlock lock; // (Mandatory) You need to implement the spinlock for your watchdog. 167e41f4b71Sopenharmony_ci volatile unsigned char *regBase; // (Mandatory) Register base address used for address mapping. 168e41f4b71Sopenharmony_ci uint32_t phyBase; // (Mandatory) Physical base address used for address mapping. 169e41f4b71Sopenharmony_ci uint32_t regStep; // (Mandatory) Register offset step used for address mapping. 170e41f4b71Sopenharmony_ci }; 171e41f4b71Sopenharmony_ci 172e41f4b71Sopenharmony_ci struct WatchdogCntlr { // WatchdogCntlr is the controller structure at the core layer. The Init function assigns values to WatchdogCntlr. 173e41f4b71Sopenharmony_ci struct IDeviceIoService service; // Driver service. 174e41f4b71Sopenharmony_ci struct HdfDeviceObject *device; // Driver device object. 175e41f4b71Sopenharmony_ci OsalSpinlock lock; // Spinlock. 176e41f4b71Sopenharmony_ci struct WatchdogMethod *ops; // Hook functions. 177e41f4b71Sopenharmony_ci int16_t wdtId; // Watchdog ID. 178e41f4b71Sopenharmony_ci void *priv; // Private data. 179e41f4b71Sopenharmony_ci }; 180e41f4b71Sopenharmony_ci ``` 181e41f4b71Sopenharmony_ci 182e41f4b71Sopenharmony_ci - Instantiate **WatchdogMethod** in **WatchdogCntlr**. 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci ```c 185e41f4b71Sopenharmony_ci static struct WatchdogMethod g_method = { // Instantiate the hook functions. 186e41f4b71Sopenharmony_ci .getStatus = Hi35xxWatchdogGetStatus, // Obtain the watchdog status. 187e41f4b71Sopenharmony_ci .start = Hi35xxWatchdogStart, // Start the watchdog. 188e41f4b71Sopenharmony_ci .stop = Hi35xxWatchdogStop, // Stop the watchdog. 189e41f4b71Sopenharmony_ci .setTimeout = Hi35xxWatchdogSetTimeout, // Set the watchdog timeout duration. 190e41f4b71Sopenharmony_ci .getTimeout = Hi35xxWatchdogGetTimeout, //Obtain the watchdog timeout duration. 191e41f4b71Sopenharmony_ci .feed = Hi35xxWatchdogFeed, // Feed the watchdog. 192e41f4b71Sopenharmony_ci }; 193e41f4b71Sopenharmony_ci ``` 194e41f4b71Sopenharmony_ci 195e41f4b71Sopenharmony_ci - Implement the **Init** and **Bind** functions. 196e41f4b71Sopenharmony_ci 197e41f4b71Sopenharmony_ci Input parameter: 198e41f4b71Sopenharmony_ci 199e41f4b71Sopenharmony_ci **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 200e41f4b71Sopenharmony_ci 201e41f4b71Sopenharmony_ci Return value: 202e41f4b71Sopenharmony_ci 203e41f4b71Sopenharmony_ci **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. 204e41f4b71Sopenharmony_ci 205e41f4b71Sopenharmony_ci **Table 2** Description of HDF_STATUS 206e41f4b71Sopenharmony_ci 207e41f4b71Sopenharmony_ci | Status| Description| 208e41f4b71Sopenharmony_ci | -------- | -------- | 209e41f4b71Sopenharmony_ci | HDF_ERR_INVALID_OBJECT | Invalid controller object.| 210e41f4b71Sopenharmony_ci | HDF_ERR_MALLOC_FAIL | Failed to allocate memory.| 211e41f4b71Sopenharmony_ci | HDF_ERR_IO | I/O error.| 212e41f4b71Sopenharmony_ci | HDF_SUCCESS | Initialization successful.| 213e41f4b71Sopenharmony_ci | HDF_FAILURE | Initialization failed.| 214e41f4b71Sopenharmony_ci 215e41f4b71Sopenharmony_ci Function description: 216e41f4b71Sopenharmony_ci 217e41f4b71Sopenharmony_ci Initializes the custom structure object and **WatchdogCntlr**, and calls **WatchdogCntlrAdd()** at the core layer to add the watchdog controller. 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci ```c 220e41f4b71Sopenharmony_ci // Generally, the Init function initializes the members of the Hi35xxWatchdog structure based on the attribute values in **HdfDeviceObject**. 221e41f4b71Sopenharmony_ci // In watchdog_hi35xx.c, it is implemented by the Bind function. 222e41f4b71Sopenharmony_ci static int32_t Hi35xxWatchdogInit(struct HdfDeviceObject *device) 223e41f4b71Sopenharmony_ci { 224e41f4b71Sopenharmony_ci (void)device; 225e41f4b71Sopenharmony_ci return HDF_SUCCESS; 226e41f4b71Sopenharmony_ci } 227e41f4b71Sopenharmony_ci 228e41f4b71Sopenharmony_ci static int32_t Hi35xxWatchdogBind(struct HdfDeviceObject *device) 229e41f4b71Sopenharmony_ci { 230e41f4b71Sopenharmony_ci int32_t ret; 231e41f4b71Sopenharmony_ci struct Hi35xxWatchdog *hwdt = NULL; 232e41f4b71Sopenharmony_ci ... 233e41f4b71Sopenharmony_ci hwdt = (struct Hi35xxWatchdog *)OsalMemCalloc(sizeof(*hwdt)); // Allocate memory for the Hi35xxWatchdog structure pointer. 234e41f4b71Sopenharmony_ci ... 235e41f4b71Sopenharmony_ci hwdt->regBase = OsalIoRemap(hwdt->phyBase, hwdt->regStep); // Address mapping. 236e41f4b71Sopenharmony_ci ... 237e41f4b71Sopenharmony_ci hwdt->wdt.priv = (void *)device->property; // (Mandatory) Use the device attributes to assign values to privr, but priv is not called later. 238e41f4b71Sopenharmony_ci //If the priv member is required, instantiate getPriv() and releasePriv() of WatchdogMethod. 239e41f4b71Sopenharmony_ci hwdt->wdt.ops = &g_method; // (Mandatory) Hook the WatchdogMethod instance. 240e41f4b71Sopenharmony_ci hwdt->wdt.device = device; // (Mandatory) Enable conversion between HdfDeviceObject and WatchdogcCntlr. 241e41f4b71Sopenharmony_ci 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. 242e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { // If the operation fails, remove the mapping and release the resources requested by the Init function. 243e41f4b71Sopenharmony_ci OsalIoUnmap((void *)hwdt->regBase); 244e41f4b71Sopenharmony_ci OsalMemFree(hwdt); 245e41f4b71Sopenharmony_ci return ret; 246e41f4b71Sopenharmony_ci } 247e41f4b71Sopenharmony_ci return HDF_SUCCESS; 248e41f4b71Sopenharmony_ci } 249e41f4b71Sopenharmony_ci ``` 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci - Implement the **Release** function. 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci Input parameter: 254e41f4b71Sopenharmony_ci 255e41f4b71Sopenharmony_ci **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs. 256e41f4b71Sopenharmony_ci 257e41f4b71Sopenharmony_ci Return value: 258e41f4b71Sopenharmony_ci 259e41f4b71Sopenharmony_ci No value is returned. 260e41f4b71Sopenharmony_ci 261e41f4b71Sopenharmony_ci Function description: 262e41f4b71Sopenharmony_ci 263e41f4b71Sopenharmony_ci 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. 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci ```c 266e41f4b71Sopenharmony_ci static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device) 267e41f4b71Sopenharmony_ci { 268e41f4b71Sopenharmony_ci struct WatchdogCntlr *wdt = NULL; 269e41f4b71Sopenharmony_ci struct Hi35xxWatchdog *hwdt = NULL; 270e41f4b71Sopenharmony_ci ... 271e41f4b71Sopenharmony_ci wdt = WatchdogCntlrFromDevice(device); // (Mandatory) Obtain WatchdogCntlr through device. 272e41f4b71Sopenharmony_ci ... 273e41f4b71Sopenharmony_ci if (wdt == NULL) { 274e41f4b71Sopenharmony_ci return; 275e41f4b71Sopenharmony_ci } 276e41f4b71Sopenharmony_ci WatchdogCntlrRemove(wdt); // (Mandatory) Call WatchdogCntlrRemove to release the WatchdogCntlr object. 277e41f4b71Sopenharmony_ci hwdt = (struct Hi35xxWatchdog *)wdt; // Convert WatchdogCntlr to Hi35xxWatchdog. 278e41f4b71Sopenharmony_ci if (hwdt->regBase != NULL) { // (Mandatory) Remove the address mapping. 279e41f4b71Sopenharmony_ci OsalIoUnmap((void *)hwdt->regBase); 280e41f4b71Sopenharmony_ci hwdt->regBase = NULL; 281e41f4b71Sopenharmony_ci } 282e41f4b71Sopenharmony_ci OsalMemFree(hwdt); // (Mandatory) Release the memory occupied by the custom object. 283e41f4b71Sopenharmony_ci } 284e41f4b71Sopenharmony_ci ``` 285e41f4b71Sopenharmony_ci 286e41f4b71Sopenharmony_ci4. Debug the driver. 287e41f4b71Sopenharmony_ci 288e41f4b71Sopenharmony_ci (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