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