1# ADC<a name="EN-US_TOPIC_0000001153677754"></a> 2 3## Overview<a name="section268031773165048"></a> 4 5The analog-to-digital converter \(ADC\) is a device that converts analog signals into digital signals. In the Hardware Driver Foundation \(HDF\), the ADC module uses the unified service mode for API adaptation. In this mode, a device service is used as the ADC manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the ADC has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. 6 7**Figure 1** Unified service mode<a name="fig14423182615525"></a> 8 9 10## Available APIs<a name="section752964871810"></a> 11 12### AdcMethod<a name="section1618135285210"></a> 13 14``` 15struct AdcMethod { 16 int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val); 17 int32_t (*start)(struct AdcDevice *device); 18 int32_t (*stop)(struct AdcDevice *device); 19}; 20``` 21 22**Table 1** Callbacks for the members in the AdcMethod structure 23 24<a name="table1943202316536"></a> 25<table><thead align="left"><tr id="row2451223135315"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p845123185313"><a name="p845123185313"></a><a name="p845123185313"></a>Callback</p> 26</th> 27<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p345192315311"><a name="p345192315311"></a><a name="p345192315311"></a>Input Parameter</p> 28</th> 29<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p74512313536"><a name="p74512313536"></a><a name="p74512313536"></a>Output Parameter</p> 30</th> 31<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p174542313531"><a name="p174542313531"></a><a name="p174542313531"></a>Return Value</p> 32</th> 33<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p445112315535"><a name="p445112315535"></a><a name="p445112315535"></a>Description</p> 34</th> 35</tr> 36</thead> 37<tbody><tr id="row545102316536"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p14562345312"><a name="p14562345312"></a><a name="p14562345312"></a>read</p> 38</td> 39<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p474720389561"><a name="p474720389561"></a><a name="p474720389561"></a><strong id="b167472038115611"><a name="b167472038115611"></a><a name="b167472038115611"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p> 40<p id="p14459238536"><a name="p14459238536"></a><a name="p14459238536"></a><strong id="b179891252205514"><a name="b179891252205514"></a><a name="b179891252205514"></a>channel</strong>: channel ID of the uint32_t type.</p> 41</td> 42<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p746423195320"><a name="p746423195320"></a><a name="p746423195320"></a><strong id="b626111125816"><a name="b626111125816"></a><a name="b626111125816"></a>val</strong>: pointer to the signal data to be transmitted. It is of the uint32_t type.</p> 43</td> 44<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1746192315311"><a name="p1746192315311"></a><a name="p1746192315311"></a>HDF_STATUS</p> 45</td> 46<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p146152311537"><a name="p146152311537"></a><a name="p146152311537"></a>Reads the signal data sampled by the ADC.</p> 47</td> 48</tr> 49<tr id="row6461236531"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p446182316538"><a name="p446182316538"></a><a name="p446182316538"></a>stop</p> 50</td> 51<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1446112318536"><a name="p1446112318536"></a><a name="p1446112318536"></a><strong id="b345886135912"><a name="b345886135912"></a><a name="b345886135912"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p> 52</td> 53<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p4461823125317"><a name="p4461823125317"></a><a name="p4461823125317"></a>–</p> 54</td> 55<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1346122314530"><a name="p1346122314530"></a><a name="p1346122314530"></a>HDF_STATUS</p> 56</td> 57<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1346223185318"><a name="p1346223185318"></a><a name="p1346223185318"></a>Stops the ADC device.</p> 58</td> 59</tr> 60<tr id="row194622375313"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p144642305313"><a name="p144642305313"></a><a name="p144642305313"></a>start</p> 61</td> 62<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p17461323185314"><a name="p17461323185314"></a><a name="p17461323185314"></a><strong id="b1988212105110"><a name="b1988212105110"></a><a name="b1988212105110"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p> 63</td> 64<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1146623105317"><a name="p1146623105317"></a><a name="p1146623105317"></a>–</p> 65</td> 66<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p546132311535"><a name="p546132311535"></a><a name="p546132311535"></a>HDF_STATUS</p> 67</td> 68<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1471623195311"><a name="p1471623195311"></a><a name="p1471623195311"></a>Starts the ADC device.</p> 69</td> 70</tr> 71</tbody> 72</table> 73 74## How to Develop<a name="section100579767165048"></a> 75 76The ADC module adaptation involves the following steps: 77 781. Instantiate the driver entry. 79 - Instantiate the **HdfDriverEntry** structure. 80 - Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF. 81 822. Configure attribute files. 83 - Add the **deviceNode** information to the **device\_info.hcs** file. 84 - \(Optional\) Add the **adc\_config.hcs** file. 85 863. Instantiate the ADC controller object. 87 - Initialize **AdcDevice**. 88 - Instantiate **AdcMethod** in the **AdcDevice** object. 89 90 > **NOTE** 91 92 >For details, see [Available APIs](#available-apis). 93 94 954. Debug the driver. 96 - \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the signal collection is successful. 97 98 99## Development Example<a name="section1745221471165048"></a> 100 101The following uses **adc\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions. 102 1031. Instantiate the driver entry. 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. 104 105 Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits. 106 107 - ADC driver entry reference 108 109 Many devices may connect to the ADC. In the HDF, a manager object needs to be created for the ADC. When a device needs to be started, the manager object locates the device based on the specified parameters. 110 111 The driver of the ADC manager is implemented by the core layer. Vendors do not need to pay attention to the implementation of this part. However, when they implement the **Init** function, the **AdcDeviceAdd** function of the core layer must be called to implement the corresponding features. 112 113 ``` 114 static struct HdfDriverEntry g_hi35xxAdcDriverEntry = { 115 .moduleVersion = 1, 116 .Init = Hi35xxAdcInit, 117 .Release = Hi35xxAdcRelease, 118 .moduleName = "hi35xx_adc_driver",// (Mandatory) This parameter must be the same as that in the .hcs file. 119 }; 120 HDF_INIT(g_hi35xxAdcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. 121 122 // Driver entry of the adc_core.c manager service at the core layer 123 struct HdfDriverEntry g_adcManagerEntry = { 124 .moduleVersion = 1, 125 .Init = AdcManagerInit, 126 .Release = AdcManagerRelease, 127 .moduleName = "HDF_PLATFORM_ADC_MANAGER",// This parameter corresponds to device0 in the device_info file. 128 }; 129 HDF_INIT(g_adcManagerEntry); 130 ``` 131 1322. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **adc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **AdcDevice** members at the core layer. 133 134 In the unified service mode, the first device node in the **device\_info** file must be the ADC manager, and the parameters must be set as follows: 135 136 <a name="table1344068233165048"></a> 137 <table><thead align="left"><tr id="row1551612465165048"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1856185125165048p0"><a name="entry1856185125165048p0"></a><a name="entry1856185125165048p0"></a>Member</p> 138 </th> 139 <th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry720672143165048p0"><a name="entry720672143165048p0"></a><a name="entry720672143165048p0"></a>Value</p> 140 </th> 141 </tr> 142 </thead> 143 <tbody><tr id="row583452627165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry747665129165048p0"><a name="entry747665129165048p0"></a><a name="entry747665129165048p0"></a>moduleName</p> 144 </td> 145 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry912596825165048p0"><a name="entry912596825165048p0"></a><a name="entry912596825165048p0"></a>It has a fixed value of <strong id="b581184091716"><a name="b581184091716"></a><a name="b581184091716"></a>HDF_PLATFORM_ADC_MANAGER</strong>.</p> 146 </td> 147 </tr> 148 <tr id="row218211231165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry568759156165048p0"><a name="entry568759156165048p0"></a><a name="entry568759156165048p0"></a>serviceName</p> 149 </td> 150 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1349637957165048p0"><a name="entry1349637957165048p0"></a><a name="entry1349637957165048p0"></a>–</p> 151 </td> 152 </tr> 153 <tr id="row1166331861165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1142726988165048p0"><a name="entry1142726988165048p0"></a><a name="entry1142726988165048p0"></a>policy</p> 154 </td> 155 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry781016408165048p0"><a name="entry781016408165048p0"></a><a name="entry781016408165048p0"></a>The value is <strong id="b229121291813"><a name="b229121291813"></a><a name="b229121291813"></a>0</strong>, which indicates that no service is published.</p> 156 </td> 157 </tr> 158 <tr id="row1822624516165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry982991296165048p0"><a name="entry982991296165048p0"></a><a name="entry982991296165048p0"></a>deviceMatchAttr</p> 159 </td> 160 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry367170471165048p0"><a name="entry367170471165048p0"></a><a name="entry367170471165048p0"></a>This parameter is not used.</p> 161 </td> 162 </tr> 163 </tbody> 164 </table> 165 166 Configure ADC controller information from the second node. This node specifies a type of ADC controllers rather than an ADC controller. In this example, there is only one ADC device. If there are multiple ADC devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **adc\_config** file. 167 168 - **device\_info.hcs** configuration reference 169 170 ``` 171 root { 172 device_info { 173 platform :: host { 174 device_adc :: device { 175 device0 :: deviceNode { 176 policy = 0; 177 priority = 50; 178 permission = 0644; 179 moduleName = "HDF_PLATFORM_ADC_MANAGER"; 180 serviceName = "HDF_PLATFORM_ADC_MANAGER"; 181 } 182 device1 :: deviceNode { 183 policy = 0; // The value 0 indicates that no service needs to be published. 184 priority = 55; // Driver startup priority 185 permission = 0644; // Permission to create device nodes for the driver 186 moduleName = "hi35xx_adc_driver"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. 187 serviceName = "HI35XX_ADC_DRIVER"; // (Mandatory) Unique name of the service published by the driver 188 deviceMatchAttr = "hisilicon_hi35xx_adc";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller in adc_config.hcs. 189 } // The specific controller information is in adc_config.hcs. 190 } 191 } 192 } 193 } 194 ``` 195 196 - adc\_config.hcs configuration reference 197 198 ``` 199 root { 200 platform { 201 adc_config_hi35xx { 202 match_attr = "hisilicon_hi35xx_adc"; 203 template adc_device { 204 regBasePhy = 0x120e0000;// Physical base address of the register 205 regSize = 0x34; // Bit width of the register 206 deviceNum = 0; // Device number 207 validChannel = 0x1; // Valid channel 208 dataWidth = 10; // Data bit width of received signals 209 scanMode = 1; // Scan mode 210 delta = 0; // Delta parameter 211 deglitch = 0; 212 glitchSample = 5000; 213 rate = 20000; 214 } 215 device_0 :: adc_device { 216 deviceNum = 0; 217 validChannel = 0x2; 218 } 219 } 220 } 221 } 222 ``` 223 2243. Initialize the **AdcDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **AdcMethod** \(used to call underlying functions of the driver\) in **AdcDevice**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\). 225 - Custom structure reference 226 227 To the driver, the custom structure carries parameters and data. The values in the **adc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the **AdcDevice** object at the core layer. 228 229 ``` 230 struct Hi35xxAdcDevice { 231 struct AdcDevice device;// (Mandatory) Control object of the core layer. For details, see the description of AdcDevice. 232 volatile unsigned char *regBase;// (Mandatory) Base address of the register 233 volatile unsigned char *pinCtrlBase; 234 uint32_t regBasePhy; // (Mandatory) Physical base address of the register 235 uint32_t regSize; // (mandatory) Bit width of the register 236 uint32_t deviceNum; // (Mandatory) Device number 237 uint32_t dataWidth; // (Mandatory) Data bit width of received signals 238 uint32_t validChannel; // (Mandatory) Valid channel 239 uint32_t scanMode; // (Mandatory) Scan mode 240 uint32_t delta; 241 uint32_t deglitch; 242 uint32_t glitchSample; 243 uint32_t rate; // (Mandatory) Sampling rate 244 }; 245 246 // AdcDevice is the core layer controller structure. Its members are assigned with values by using the Init function. 247 struct AdcDevice { 248 const struct AdcMethod *ops; 249 OsalSpinlock spin; 250 uint32_t devNum; 251 uint32_t chanNum; 252 const struct AdcLockMethod *lockOps; 253 void *priv; 254 }; 255 ``` 256 257 - Instantiate the callback function structure **AdcMethod** in **AdcDevice**. The **AdcLockMethod** callback function structure is not implemented in this example. To instantiate the structure, refer to the I2C driver development. Other members are initialized in the **Init** function. 258 259 ``` 260 static const struct AdcMethod g_method = { 261 .read = Hi35xxAdcRead, 262 .stop = Hi35xxAdcStop, 263 .start = Hi35xxAdcStart, 264 }; 265 ``` 266 267 - Init function 268 269 Input parameters: 270 271 **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. 272 273 Return values: 274 275 HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\) 276 277 <a name="table127573104165048"></a> 278 <table><thead align="left"><tr id="row1932243367165048"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry405408385165048p0"><a name="entry405408385165048p0"></a><a name="entry405408385165048p0"></a>Status (Value)</p> 279 </th> 280 <th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry407875094165048p0"><a name="entry407875094165048p0"></a><a name="entry407875094165048p0"></a>Description</p> 281 </th> 282 </tr> 283 </thead> 284 <tbody><tr id="row1845195554165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry144793493165048p0"><a name="entry144793493165048p0"></a><a name="entry144793493165048p0"></a>HDF_ERR_INVALID_OBJECT</p> 285 </td> 286 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1933449399165048p0"><a name="entry1933449399165048p0"></a><a name="entry1933449399165048p0"></a>Invalid controller object</p> 287 </td> 288 </tr> 289 <tr id="row1203086670165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry766973904165048p0"><a name="entry766973904165048p0"></a><a name="entry766973904165048p0"></a>HDF_ERR_INVALID_PARAM</p> 290 </td> 291 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry999036326165048p0"><a name="entry999036326165048p0"></a><a name="entry999036326165048p0"></a>Invalid parameter</p> 292 </td> 293 </tr> 294 <tr id="row1147526196165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry271913224165048p0"><a name="entry271913224165048p0"></a><a name="entry271913224165048p0"></a>HDF_ERR_MALLOC_FAIL</p> 295 </td> 296 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1349459344165048p0"><a name="entry1349459344165048p0"></a><a name="entry1349459344165048p0"></a>Failed to allocate memory</p> 297 </td> 298 </tr> 299 <tr id="row42206428165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry826579070165048p0"><a name="entry826579070165048p0"></a><a name="entry826579070165048p0"></a>HDF_ERR_IO</p> 300 </td> 301 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry740637684165048p0"><a name="entry740637684165048p0"></a><a name="entry740637684165048p0"></a>I/O error</p> 302 </td> 303 </tr> 304 <tr id="row456623770165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry2126491887165048p0"><a name="entry2126491887165048p0"></a><a name="entry2126491887165048p0"></a>HDF_SUCCESS</p> 305 </td> 306 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1585614415165048p0"><a name="entry1585614415165048p0"></a><a name="entry1585614415165048p0"></a>Transmission successful</p> 307 </td> 308 </tr> 309 <tr id="row2048732992165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry131232818165048p0"><a name="entry131232818165048p0"></a><a name="entry131232818165048p0"></a>HDF_FAILURE</p> 310 </td> 311 <td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry42178503165048p0"><a name="entry42178503165048p0"></a><a name="entry42178503165048p0"></a>Transmission failed</p> 312 </td> 313 </tr> 314 </tbody> 315 </table> 316 317 Function description: 318 319 Initializes the custom structure object and **AdcDevice**, and calls the **AdcDeviceAdd** function at the core layer. 320 321 ``` 322 static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device) 323 { 324 int32_t ret; 325 struct DeviceResourceNode *childNode = NULL; 326 ... 327 // Traverse and parse all nodes in adc_config.hcs and call the Hi35xxAdcParseInit function to initialize the devices separately. 328 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { 329 ret = Hi35xxAdcParseInit(device, childNode);// For details about the function definition, see the following description. 330 ... 331 } 332 return ret; 333 } 334 335 static int32_t Hi35xxAdcParseInit(struct HdfDeviceObject *device, struct DeviceResourceNode *node) 336 { 337 int32_t ret; 338 struct Hi35xxAdcDevice *hi35xx = NULL; // (Mandatory) Custom structure object 339 (void)device; 340 341 hi35xx = (struct Hi35xxAdcDevice *)OsalMemCalloc(sizeof(*hi35xx)); // (Mandatory) Memory allocation 342 ... 343 ret = Hi35xxAdcReadDrs(hi35xx, node); // (Mandatory) Fill the default values in the adc_config file to the structure. 344 ... 345 hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);// (Mandatory) Address mapping 346 ... 347 hi35xx->pinCtrlBase = OsalIoRemap(HI35XX_ADC_IO_CONFIG_BASE, HI35XX_ADC_IO_CONFIG_SIZE); 348 ... 349 Hi35xxAdcDeviceInit(hi35xx); // (Mandatory) Initialize the ADC. 350 hi35xx->device.priv = (void *)node; // (Mandatory) Store device attributes. 351 hi35xx->device.devNum = hi35xx->deviceNum;// (Mandatory) Initialize the AdcDevice members. 352 hi35xx->device.ops = &g_method; // (Mandatory) Mount the AdcMethod instance object. 353 ret = AdcDeviceAdd(&hi35xx->device); // (Mandatory and important) Call this function to set the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned. 354 ... 355 return HDF_SUCCESS; 356 357 __ERR__: 358 if (hi35xx != NULL) { // If the operation fails, you need to execute the initialization function reversely. 359 if (hi35xx->regBase != NULL) { 360 OsalIoUnmap((void *)hi35xx->regBase); 361 hi35xx->regBase = NULL; 362 } 363 AdcDeviceRemove(&hi35xx->device); 364 OsalMemFree(hi35xx); 365 } 366 return ret; 367 } 368 ``` 369 370 - Release function 371 372 Input parameters: 373 374 **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information. 375 376 Return values: 377 378 – 379 380 Function description: 381 382 Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations. 383 384 ``` 385 static void Hi35xxAdcRelease(struct HdfDeviceObject *device) 386 { 387 const struct DeviceResourceNode *childNode = NULL; 388 ... 389 // Traverse and parse all nodes in adc_config.hcs and perform the release operation on each node. 390 DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { 391 Hi35xxAdcRemoveByNode(childNode);// The function definition is as follows: 392 } 393 } 394 395 static void Hi35xxAdcRemoveByNode(const struct DeviceResourceNode *node) 396 { 397 int32_t ret; 398 int32_t deviceNum; 399 struct AdcDevice *device = NULL; 400 struct Hi35xxAdcDevice *hi35xx = NULL; 401 struct DeviceResourceIface *drsOps = NULL; 402 403 drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 404 ... 405 ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0); 406 ... 407 // You can call the AdcDeviceGet function to obtain the AdcDevice object based on deviceNum and call the AdcDeviceRemove function to release the AdcDevice object. 408 device = AdcDeviceGet(deviceNum); 409 if (device != NULL && device->priv == node) { 410 AdcDevicePut(device); 411 AdcDeviceRemove(device); // (Mandatory) Remove the AdcDevice object from the driver manager. 412 hi35xx = (struct Hi35xxAdcDevice *)device;// (Mandatory) Obtain the custom object through forced conversion and release the object. 413 OsalIoUnmap((void *)hi35xx->regBase); 414 OsalMemFree(hi35xx); 415 } 416 return 417 ``` 418 419 420 421