• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ![image](figures/independent-service-mode.png "Watchdog independent service mode")
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   > ![](../public_sys-resources/icon-note.gif) **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