1e41f4b71Sopenharmony_ci# Pin
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## Overview
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci### Function
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ciThe pin module, also called pin controller, manages pin resources of the system on a chip (SoC) and implements the pin multiplexing function.
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci### Basic Concepts
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ciPin is a software concept designed to uniformly manage SoC pins, implement pin multiplexing, and set electrical features of pins.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci- SoC
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci  An SoC is a chip that integrates microprocessors, analog IP cores, digital IP cores, and memory for specific purposes.
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci- Pin multiplexing
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci  When the number of pins of a chip cannot handle the increasing connection requests, you can set software registers to make the pins to work in different states.
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci### Working Principles
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ciIn the Hardware Driver Foundation (HDF), the pin module uses the unified service mode for API adaptation. In this mode, a device service is used as the pin manager to handle access requests from the devices of the same type in a unified manner. The unified service mode applies to the scenario where there are many device objects of the same type. If the independent service mode is used in this case, more device nodes need to be configured and more memory resources will be consumed. The following figure shows the unified service mode.
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ciIn the unified service mode, the core layer manages all controllers in a unified manner and publishes a service for the interface layer. That is, the driver does not need to publish a service for each controller.
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ciThe pin module is divided into the following layers:
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and function of a pin, and releasing a pin.
30e41f4b71Sopenharmony_ci- Core layer: provides APIs for matching pin resources, adding and removing a pin controller, and managing pins. The core layer interacts with the adaptation layer through hook functions.
31e41f4b71Sopenharmony_ci- Adaptation layer: instantiates the hook functions to implement specific features.
32e41f4b71Sopenharmony_ci
33e41f4b71Sopenharmony_ci**Figure 1** Unified service mode
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci![](figures/unified-service-mode.png)
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci### Constraints
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ciThe pin module supports only the LiteOS-A kernel of the small system.
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci## Development Guidelines
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci### When to Use
44e41f4b71Sopenharmony_ci
45e41f4b71Sopenharmony_ciThe pin module is used to manage pin resources. Before using the SoC with the HDF, you need to perform PIN driver adaptation.
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci### Available APIs
48e41f4b71Sopenharmony_ci
49e41f4b71Sopenharmony_ciTo enable the upper layer to successfully operate pins by calling the pin driver APIs, hook functions are defined in **//drivers/hdf_core/framework/support/platform/include/pin/pin_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.
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ci**PinCntlrMethod**:
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci```c
54e41f4b71Sopenharmony_cistruct PinCntlrMethod {
55e41f4b71Sopenharmony_ci    int32_t (*SetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType pullType);
56e41f4b71Sopenharmony_ci    int32_t (*GetPinPull)(struct PinCntlr *cntlr, uint32_t index, enum PinPullType *pullType);
57e41f4b71Sopenharmony_ci    int32_t (*SetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t strength);
58e41f4b71Sopenharmony_ci    int32_t (*GetPinStrength)(struct PinCntlr *cntlr, uint32_t index, uint32_t *strength);
59e41f4b71Sopenharmony_ci    int32_t (*SetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char *funcName);
60e41f4b71Sopenharmony_ci    int32_t (*GetPinFunc)(struct PinCntlr *cntlr, uint32_t index, const char **funcName);
61e41f4b71Sopenharmony_ci};
62e41f4b71Sopenharmony_ci```
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci**Table 1** Hook functions in PinCntlrMethod
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci| Function    | Input Parameter                                       | Output Parameter                                  | Return Value| Description|
67e41f4b71Sopenharmony_ci| ------------ | ------------------------------------------- | ------ | ---- | ---- |
68e41f4b71Sopenharmony_ci| SetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable. <br>**pullType**: pull type of the pin.| -|HDF_STATUS|Sets the pull type of a pin.|
69e41f4b71Sopenharmony_ci| GetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable. | **pullType**: pointer to the pull type obtained.| HDF_STATUS| Obtains the pull type of a pin.|
70e41f4b71Sopenharmony_ci| SetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable. <br>**strength**: pull type to set, which is a uint32_t variable.| -| HDF_STATUS| Sets the pull strength of a pin.|
71e41f4b71Sopenharmony_ci| GetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable. | **strength**: pointer to the pull strength obtained.| HDF_STATUS| Obtains the pull strength of a pin.|
72e41f4b71Sopenharmony_ci| SetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable. <br>**funcName**: pointer to the pin function to set. It is a character constant.| -| HDF_STATUS| Sets the pin function.|
73e41f4b71Sopenharmony_ci| GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable. | **funcName**: double pointer to the PIN function obtained. It is a character constant.| HDF_STATUS| Obtains the pin function.|
74e41f4b71Sopenharmony_ci
75e41f4b71Sopenharmony_ci### How to Develop
76e41f4b71Sopenharmony_ci
77e41f4b71Sopenharmony_ciThe pin module adaptation procedure is as follows:
78e41f4b71Sopenharmony_ci
79e41f4b71Sopenharmony_ci- Instantiate the driver entry.
80e41f4b71Sopenharmony_ci- Configure attribute files.
81e41f4b71Sopenharmony_ci- Instantiate the pin controller object.
82e41f4b71Sopenharmony_ci- Debug the driver.
83e41f4b71Sopenharmony_ci
84e41f4b71Sopenharmony_ci### Example
85e41f4b71Sopenharmony_ci
86e41f4b71Sopenharmony_ciThe following uses the **//device_soc_hisilicon/common/platform/pin/pin_hi35xx.c** driver of the Hi3516D V300 development board as an example to describe the pin driver adaptation.
87e41f4b71Sopenharmony_ci
88e41f4b71Sopenharmony_ci1. Instantiate the driver entry.
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_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, 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.
91e41f4b71Sopenharmony_ci   Generally, the HDF calls **Bind()** and then **Init()** to load a driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ci   PIN driver entry example:
94e41f4b71Sopenharmony_ci
95e41f4b71Sopenharmony_ci   ```c
96e41f4b71Sopenharmony_ci   static struct HdfDriverEntry g_hi35xxPinDriverEntry = {
97e41f4b71Sopenharmony_ci       .moduleVersion = 1,
98e41f4b71Sopenharmony_ci       .Bind = Hi35xxPinBind,
99e41f4b71Sopenharmony_ci       .Init = Hi35xxPinInit,
100e41f4b71Sopenharmony_ci       .Release = Hi35xxPinRelease,
101e41f4b71Sopenharmony_ci       .moduleName = "hi35xx_pin_driver",  // (Mandatory) The value must be the same as that of moduleName in the .hcs file.
102e41f4b71Sopenharmony_ci   };
103e41f4b71Sopenharmony_ci   HDF_INIT(g_hi35xxPinDriverEntry);      // Call HDF_INIT to register the driver entry with the HDF.
104e41f4b71Sopenharmony_ci   ```
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci2. Configure attribute files.
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_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 two pin controllers as an example. If there are more pin controllers, add the deviceNode information to the **device_info.hcs** file for each controller. The device attribute values configured in **pin_config.hcs** are closely related to the driver implementation and default values or value ranges of the **PinCntlr** members at the core layer.
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci   - **device_info.hcs** example
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci      Add the deviceNode information to the **//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ci      ```c
115e41f4b71Sopenharmony_ci      root {
116e41f4b71Sopenharmony_ci          device_info {
117e41f4b71Sopenharmony_ci              platform :: host {
118e41f4b71Sopenharmony_ci                  hostName = "platform_host";
119e41f4b71Sopenharmony_ci                  priority = 50;
120e41f4b71Sopenharmony_ci                  device_pin :: device {
121e41f4b71Sopenharmony_ci                      device0 :: deviceNode {                              // Used to manage pins and release services in a unified manner.
122e41f4b71Sopenharmony_ci                          policy = 2;                                      // The value 2 means to publish services for both kernel- and user-mode processes. 
123e41f4b71Sopenharmony_ci                          priority = 8;                                    // Driver startup priority.
124e41f4b71Sopenharmony_ci                          permission = 0644;                               // Permission for the device node created.
125e41f4b71Sopenharmony_ci                          moduleName = "HDF_PLATFORM_PIN_MANAGER";
126e41f4b71Sopenharmony_ci                          serviceName = "HDF_PLATFORM_PIN_MANAGER";
127e41f4b71Sopenharmony_ci                      }
128e41f4b71Sopenharmony_ci                      device1:: deviceNode {                               // Configure an HDF device node for each pin controller.
129e41f4b71Sopenharmony_ci                          policy = 0;
130e41f4b71Sopenharmony_ci                          priority = 10;                                   // Driver startup priority.
131e41f4b71Sopenharmony_ci                          permission = 0644;                               // Permission for the device node created.
132e41f4b71Sopenharmony_ci                          moduleName = "hi35xx_pin_driver";                // (mandatory) Driver name, which must be the same as moduleName in the driver entry.
133e41f4b71Sopenharmony_ci                          deviceMatchAttr = "hisilicon_hi35xx_pin_0";      // (Mandatory) Controller private data, which must be the same as that of the controller in pin_config.hcs.
134e41f4b71Sopenharmony_ci                      }
135e41f4b71Sopenharmony_ci                      device2 :: deviceNode {
136e41f4b71Sopenharmony_ci                          policy = 0;
137e41f4b71Sopenharmony_ci                          priority = 10;
138e41f4b71Sopenharmony_ci                          permission = 0644;
139e41f4b71Sopenharmony_ci                          moduleName = "hi35xx_pin_driver";
140e41f4b71Sopenharmony_ci                          deviceMatchAttr = "hisilicon_hi35xx_pin_1";
141e41f4b71Sopenharmony_ci                      }
142e41f4b71Sopenharmony_ci                      ...
143e41f4b71Sopenharmony_ci                  }
144e41f4b71Sopenharmony_ci              }
145e41f4b71Sopenharmony_ci          }
146e41f4b71Sopenharmony_ci      }
147e41f4b71Sopenharmony_ci      ```
148e41f4b71Sopenharmony_ci
149e41f4b71Sopenharmony_ci   -  **pin_config.hcs** example:
150e41f4b71Sopenharmony_ci
151e41f4b71Sopenharmony_ci      Configure the device attributes in the **//device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs** file. The parameters are as follows:
152e41f4b71Sopenharmony_ci
153e41f4b71Sopenharmony_ci      ```c
154e41f4b71Sopenharmony_ci      root {
155e41f4b71Sopenharmony_ci          platform {
156e41f4b71Sopenharmony_ci              pin_config_hi35xx {
157e41f4b71Sopenharmony_ci                  template pin_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.
158e41f4b71Sopenharmony_ci                      number = 0;                             // (Mandatory) PIN controller number.
159e41f4b71Sopenharmony_ci                      regStartBasePhy = 0;                    // (Mandatory) Start address of the physical base address of the register.
160e41f4b71Sopenharmony_ci                      regSize = 0;                            // (Mandatory) Register size.
161e41f4b71Sopenharmony_ci                      pinCount = 0;                           // (Mandatory) Number of pins.
162e41f4b71Sopenharmony_ci                      match_attr = "";
163e41f4b71Sopenharmony_ci                      template pin_desc {
164e41f4b71Sopenharmony_ci                          pinName = "";                       // (Mandatory) Pin name.
165e41f4b71Sopenharmony_ci                              init = 0;                       // (Mandatory) Default value of the register.
166e41f4b71Sopenharmony_ci                              F0 = "";                        // (Mandatory) Function 0.
167e41f4b71Sopenharmony_ci                              F1 = "";                        // Function 1.
168e41f4b71Sopenharmony_ci                              F2 = "";                        // Function 2.
169e41f4b71Sopenharmony_ci                              F3 = "";                        // Function 3.
170e41f4b71Sopenharmony_ci                              F4 = "";                        // Function 4.
171e41f4b71Sopenharmony_ci                              F5 = "";                        // Function 5.
172e41f4b71Sopenharmony_ci                          }
173e41f4b71Sopenharmony_ci                  }
174e41f4b71Sopenharmony_ci                  controller_0 :: pin_controller {
175e41f4b71Sopenharmony_ci                      number = 0;
176e41f4b71Sopenharmony_ci                      regStartBasePhy = 0x10FF0000;
177e41f4b71Sopenharmony_ci                      regSize = 0x48;
178e41f4b71Sopenharmony_ci                      pinCount = 18;
179e41f4b71Sopenharmony_ci                      match_attr = "hisilicon_hi35xx_pin_0";
180e41f4b71Sopenharmony_ci                      T1 :: pin_desc {
181e41f4b71Sopenharmony_ci                          pinName = "T1";
182e41f4b71Sopenharmony_ci                          init = 0x0600;
183e41f4b71Sopenharmony_ci                          F0 = "EMMC_CLK";
184e41f4b71Sopenharmony_ci                          F1 = "SFC_CLK";
185e41f4b71Sopenharmony_ci                          F2 = "SFC_BOOT_MODE";
186e41f4b71Sopenharmony_ci                      }
187e41f4b71Sopenharmony_ci                      ...                                     // Add each pin under the pin controller.
188e41f4b71Sopenharmony_ci                  }
189e41f4b71Sopenharmony_ci                  ...                                         // Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the controller nodes one by one.
190e41f4b71Sopenharmony_ci              }
191e41f4b71Sopenharmony_ci          }
192e41f4b71Sopenharmony_ci      }
193e41f4b71Sopenharmony_ci      ```
194e41f4b71Sopenharmony_ci
195e41f4b71Sopenharmony_ci      After the **pin_config.hcs** file is configured, include the file in the **hdf.hcs** file. Otherwise, the configuration file cannot take effect.
196e41f4b71Sopenharmony_ci
197e41f4b71Sopenharmony_ci      ```c
198e41f4b71Sopenharmony_ci      #include "../../../../device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs" // Relative path of the file.
199e41f4b71Sopenharmony_ci      ```
200e41f4b71Sopenharmony_ci
201e41f4b71Sopenharmony_ci3. Instantiate the pin controller object.
202e41f4b71Sopenharmony_ci
203e41f4b71Sopenharmony_ci   Initialize the **PinCntlr** 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 **PinCntlrMethod** in **PinCntlr** (so that the underlying driver functions can be called).
204e41f4b71Sopenharmony_ci
205e41f4b71Sopenharmony_ci   - Define a custom structure.
206e41f4b71Sopenharmony_ci
207e41f4b71Sopenharmony_ci      To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **pin_config.hcs** file to initialize the members in the custom structure and passes important parameters to the object at the core layer.
208e41f4b71Sopenharmony_ci
209e41f4b71Sopenharmony_ci      Initialize **PinCntlr** in **Hi35xxPinCntlrInit**.
210e41f4b71Sopenharmony_ci
211e41f4b71Sopenharmony_ci      ```c
212e41f4b71Sopenharmony_ci      // Custom pin description structure.
213e41f4b71Sopenharmony_ci      struct Hi35xxPinDesc {
214e41f4b71Sopenharmony_ci          const char *pinName;                       // Pin name.
215e41f4b71Sopenharmony_ci          uint32_t init;                             // Initial value.
216e41f4b71Sopenharmony_ci          uint32_t index;                            // Pin index.
217e41f4b71Sopenharmony_ci          int32_t pullType;                          // Pull type of the pin.
218e41f4b71Sopenharmony_ci          int32_t strength;                          // Pull strength of the pin.
219e41f4b71Sopenharmony_ci          const char *func[HI35XX_PIN_FUNC_MAX];     // Array of pin function names.
220e41f4b71Sopenharmony_ci      };
221e41f4b71Sopenharmony_ci
222e41f4b71Sopenharmony_ci      /* Custom structure.
223e41f4b71Sopenharmony_ci      struct Hi35xxPinCntlr {
224e41f4b71Sopenharmony_ci          struct PinCntlr cntlr                      // Core layer control object.
225e41f4b71Sopenharmony_ci          struct Hi35xxPinDesc *desc;                // Pointer to the pin description structure.
226e41f4b71Sopenharmony_ci          volatile unsigned char *regBase;           // Register base address used for address mapping.
227e41f4b71Sopenharmony_ci          uint16_t number;                           // Pin controller number.
228e41f4b71Sopenharmony_ci          uint32_t regStartBasePhy;                  // Start address of the register physical base address.
229e41f4b71Sopenharmony_ci          uint32_t regSize;                          // Register size.
230e41f4b71Sopenharmony_ci          uint32_t pinCount;                         // Number of pins.
231e41f4b71Sopenharmony_ci      };
232e41f4b71Sopenharmony_ci
233e41f4b71Sopenharmony_ci      // PinCntlr is the controller structure at the core layer. The Init function assigns values to the members of PinCntlr.
234e41f4b71Sopenharmony_ci      struct PinCntlr {
235e41f4b71Sopenharmony_ci          struct IDeviceIoService service;           // Driver service.
236e41f4b71Sopenharmony_ci          struct HdfDeviceObject *device;            // Driver device object.
237e41f4b71Sopenharmony_ci          struct PinCntlrMethod *method;             // Hook functions.
238e41f4b71Sopenharmony_ci          struct DListHead node;                     // Linked list node.
239e41f4b71Sopenharmony_ci          OsalSpinlock spin;                         // Spinlock.
240e41f4b71Sopenharmony_ci          uint16_t number;                           // Pin controller number.
241e41f4b71Sopenharmony_ci          uint16_t pinCount;                         // Number of pins.
242e41f4b71Sopenharmony_ci          struct PinDesc *pins;                      // Pin resources.
243e41f4b71Sopenharmony_ci          void *priv;                                // Private data.
244e41f4b71Sopenharmony_ci      };
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci      // Initialize the pin controller.
247e41f4b71Sopenharmony_ci      static int32_t Hi35xxPinCntlrInit(struct HdfDeviceObject *device, struct Hi35xxPinCntlr *hi35xx)
248e41f4b71Sopenharmony_ci      {
249e41f4b71Sopenharmony_ci          struct DeviceResourceIface *drsOps = NULL;
250e41f4b71Sopenharmony_ci          int32_t ret;
251e41f4b71Sopenharmony_ci          // Read the pin controller attributes from the .hcs file.
252e41f4b71Sopenharmony_ci          drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
253e41f4b71Sopenharmony_ci          if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
254e41f4b71Sopenharmony_ci              HDF_LOGE("%s: invalid drs ops fail!", __func__);
255e41f4b71Sopenharmony_ci              return HDF_FAILURE;
256e41f4b71Sopenharmony_ci          }
257e41f4b71Sopenharmony_ci          ret = drsOps->GetUint16(device->property, "number", &hi35xx->number, 0);
258e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
259e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read number failed", __func__);
260e41f4b71Sopenharmony_ci              return ret;
261e41f4b71Sopenharmony_ci          }
262e41f4b71Sopenharmony_ci
263e41f4b71Sopenharmony_ci          if (hi35xx->number > HI35XX_PIN_MAX_NUMBER) {
264e41f4b71Sopenharmony_ci              HDF_LOGE("%s: invalid number:%u", __func__, hi35xx->number);
265e41f4b71Sopenharmony_ci              return HDF_ERR_INVALID_PARAM;
266e41f4b71Sopenharmony_ci          }
267e41f4b71Sopenharmony_ci          ret = drsOps->GetUint32(device->property, "regStartBasePhy", &hi35xx->regStartBasePhy, 0);
268e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
269e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read regStartBasePhy failed", __func__);
270e41f4b71Sopenharmony_ci              return ret;
271e41f4b71Sopenharmony_ci          }
272e41f4b71Sopenharmony_ci          ret = drsOps->GetUint32(device->property, "regSize", &hi35xx->regSize, 0);
273e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
274e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read regSize failed", __func__);
275e41f4b71Sopenharmony_ci              return ret;
276e41f4b71Sopenharmony_ci          }
277e41f4b71Sopenharmony_ci          ret = drsOps->GetUint32(device->property, "pinCount", &hi35xx->pinCount, 0);
278e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
279e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read pinCount failed", __func__);
280e41f4b71Sopenharmony_ci              return ret;
281e41f4b71Sopenharmony_ci          }
282e41f4b71Sopenharmony_ci          if (hi35xx->pinCount > PIN_MAX_CNT_PER_CNTLR) {
283e41f4b71Sopenharmony_ci              HDF_LOGE("%s: invalid number:%u", __func__, hi35xx->number);
284e41f4b71Sopenharmony_ci              return HDF_ERR_INVALID_PARAM;
285e41f4b71Sopenharmony_ci          }
286e41f4b71Sopenharmony_ci          // Assign the values read to the members of the pin controller to initialize the pin controller.
287e41f4b71Sopenharmony_ci          hi35xx->cntlr.pinCount = hi35xx->pinCount;
288e41f4b71Sopenharmony_ci          hi35xx->cntlr.number = hi35xx->number;
289e41f4b71Sopenharmony_ci          hi35xx->regBase = OsalIoRemap(hi35xx->regStartBasePhy, hi35xx->regSize); // Pin controller mapping.
290e41f4b71Sopenharmony_ci          if (hi35xx->regBase == NULL) {
291e41f4b71Sopenharmony_ci              HDF_LOGE("%s: remap Pin base failed", __func__);
292e41f4b71Sopenharmony_ci              return HDF_ERR_IO;
293e41f4b71Sopenharmony_ci          }
294e41f4b71Sopenharmony_ci          hi35xx->desc = (struct Hi35xxPinDesc *)OsalMemCalloc(sizeof(struct Hi35xxPinDesc) * hi35xx->pinCount);
295e41f4b71Sopenharmony_ci          if (hi35xx->desc == NULL) {
296e41f4b71Sopenharmony_ci              HDF_LOGE("%s: memcalloc hi35xx desc failed", __func__);
297e41f4b71Sopenharmony_ci              return HDF_ERR_MALLOC_FAIL;
298e41f4b71Sopenharmony_ci          }
299e41f4b71Sopenharmony_ci          hi35xx->cntlr.pins = (struct PinDesc *)OsalMemCalloc(sizeof(struct PinDesc) * hi35xx->pinCount);
300e41f4b71Sopenharmony_ci              if (hi35xx->desc == NULL) {
301e41f4b71Sopenharmony_ci              HDF_LOGE("%s: memcalloc hi35xx cntlr pins failed", __func__);
302e41f4b71Sopenharmony_ci              return HDF_ERR_MALLOC_FAIL;
303e41f4b71Sopenharmony_ci          }
304e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
305e41f4b71Sopenharmony_ci      }
306e41f4b71Sopenharmony_ci      ```
307e41f4b71Sopenharmony_ci
308e41f4b71Sopenharmony_ci   - Instantiate the **PinCntlrMethod** structure in **PinCntlr**.
309e41f4b71Sopenharmony_ci
310e41f4b71Sopenharmony_ci      ```c
311e41f4b71Sopenharmony_ci      static struct PinCntlrMethod g_method = {
312e41f4b71Sopenharmony_ci          .SetPinPull = Hi35xxPinSetPull,              // Set the pull type.
313e41f4b71Sopenharmony_ci          .GetPinPull = Hi35xxPinGetPull,              // Obtain the pull type.
314e41f4b71Sopenharmony_ci          .SetPinStrength = Hi35xxPinSetStrength,      // Set the pull strength.
315e41f4b71Sopenharmony_ci          .GetPinStrength = Hi35xxPinGetStrength,      // Obtain the pull strength.
316e41f4b71Sopenharmony_ci          .SetPinFunc = Hi35xxPinSetFunc,              // Set the pin functions.
317e41f4b71Sopenharmony_ci          .GetPinFunc = Hi35xxPinGetFunc,              // Obtain the pin functions.
318e41f4b71Sopenharmony_ci      };
319e41f4b71Sopenharmony_ci      ```
320e41f4b71Sopenharmony_ci
321e41f4b71Sopenharmony_ci   - Implement the **Init** function.
322e41f4b71Sopenharmony_ci
323e41f4b71Sopenharmony_ci      Input Parameter
324e41f4b71Sopenharmony_ci
325e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
326e41f4b71Sopenharmony_ci
327e41f4b71Sopenharmony_ci      Return value:
328e41f4b71Sopenharmony_ci
329e41f4b71Sopenharmony_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.
330e41f4b71Sopenharmony_ci
331e41f4b71Sopenharmony_ci      | **State**          | **Description**  |
332e41f4b71Sopenharmony_ci      | ---------------------- | -------------- |
333e41f4b71Sopenharmony_ci      | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
334e41f4b71Sopenharmony_ci      | HDF_ERR_MALLOC_FAIL    | Failed to allocate memory.  |
335e41f4b71Sopenharmony_ci      | HDF_ERR_INVALID_PARAM  | Invalid parameter.      |
336e41f4b71Sopenharmony_ci      | HDF_ERR_IO             | I/O error.      |
337e41f4b71Sopenharmony_ci      | HDF_SUCCESS            | Initialization successful.    |
338e41f4b71Sopenharmony_ci      | HDF_FAILURE            | Initialization failed.    |
339e41f4b71Sopenharmony_ci
340e41f4b71Sopenharmony_ci      Function description:
341e41f4b71Sopenharmony_ci
342e41f4b71Sopenharmony_ci      Initializes the custom structure object and **PinCntlr** members, and calls **PinCntlrAdd()** to add the pin controller to the core layer.
343e41f4b71Sopenharmony_ci
344e41f4b71Sopenharmony_ci      ```c
345e41f4b71Sopenharmony_ci      static int32_t Hi35xxPinReadFunc(struct Hi35xxPinDesc *desc, const struct DeviceResourceNode *node, struct DeviceResourceIface *drsOps)
346e41f4b71Sopenharmony_ci      {
347e41f4b71Sopenharmony_ci          int32_t ret;
348e41f4b71Sopenharmony_ci          uint32_t funcNum = 0;
349e41f4b71Sopenharmony_ci          // Read the pin function names of the pin controller child nodes from the .hcs file.
350e41f4b71Sopenharmony_ci          ret = drsOps->GetString(node, "F0", &desc->func[funcNum], "NULL");
351e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
352e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read F0 failed", __func__);
353e41f4b71Sopenharmony_ci              return ret;
354e41f4b71Sopenharmony_ci          }
355e41f4b71Sopenharmony_ci
356e41f4b71Sopenharmony_ci          funcNum++;
357e41f4b71Sopenharmony_ci          ret = drsOps->GetString(node, "F1", &desc->func[funcNum], "NULL");
358e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
359e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read F1 failed", __func__);
360e41f4b71Sopenharmony_ci              return ret;
361e41f4b71Sopenharmony_ci          }
362e41f4b71Sopenharmony_ci
363e41f4b71Sopenharmony_ci          funcNum++;
364e41f4b71Sopenharmony_ci          ...
365e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
366e41f4b71Sopenharmony_ci      }
367e41f4b71Sopenharmony_ci
368e41f4b71Sopenharmony_ci      static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node, struct Hi35xxPinCntlr *hi35xx, int32_t index)
369e41f4b71Sopenharmony_ci      {
370e41f4b71Sopenharmony_ci          int32_t ret;
371e41f4b71Sopenharmony_ci          struct DeviceResourceIface *drsOps = NULL;
372e41f4b71Sopenharmony_ci          // Read the pin attributes of the pin controller child nodes from the .hcs file.
373e41f4b71Sopenharmony_ci          drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
374e41f4b71Sopenharmony_ci          if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
375e41f4b71Sopenharmony_ci              HDF_LOGE("%s: invalid drs ops fail!", __func__);
376e41f4b71Sopenharmony_ci              return HDF_FAILURE;
377e41f4b71Sopenharmony_ci          }
378e41f4b71Sopenharmony_ci          ret = drsOps->GetString(node, "pinName", &hi35xx->desc[index].pinName, "NULL");
379e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
380e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read pinName failed", __func__);
381e41f4b71Sopenharmony_ci              return ret;
382e41f4b71Sopenharmony_ci          }
383e41f4b71Sopenharmony_ci          ...
384e41f4b71Sopenharmony_ci          ret = Hi35xxPinReadFunc(&hi35xx->desc[index], node, drsOps);
385e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
386e41f4b71Sopenharmony_ci              HDF_LOGE("%s:Pin read Func failed", __func__);
387e41f4b71Sopenharmony_ci              return ret;
388e41f4b71Sopenharmony_ci          }
389e41f4b71Sopenharmony_ci          hi35xx->cntlr.pins[index].pinName = hi35xx->desc[index].pinName;
390e41f4b71Sopenharmony_ci          hi35xx->cntlr.pins[index].priv = (void *)node;
391e41f4b71Sopenharmony_ci          ...
392e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
393e41f4b71Sopenharmony_ci      }
394e41f4b71Sopenharmony_ci
395e41f4b71Sopenharmony_ci      static int32_t Hi35xxPinInit(struct HdfDeviceObject *device)
396e41f4b71Sopenharmony_ci      {
397e41f4b71Sopenharmony_ci          ...
398e41f4b71Sopenharmony_ci          struct Hi35xxPinCntlr *hi35xx = NULL;
399e41f4b71Sopenharmony_ci          ...
400e41f4b71Sopenharmony_ci          ret = Hi35xxPinCntlrInit(device, hi35xx);                         // Initialize the pin controller.
401e41f4b71Sopenharmony_ci          ...
402e41f4b71Sopenharmony_ci          DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {   // Traverse each child node of the pin controller.
403e41f4b71Sopenharmony_ci              ret = Hi35xxPinParsePinNode(childNode, hi35xx, index);        // Parse child nodes.
404e41f4b71Sopenharmony_ci              ...
405e41f4b71Sopenharmony_ci          }
406e41f4b71Sopenharmony_ci
407e41f4b71Sopenharmony_ci          hi35xx->cntlr.method = &g_method;                                 // Attach the PinCntlrMethod instance.
408e41f4b71Sopenharmony_ci          ret = PinCntlrAdd(&hi35xx->cntlr);                                // Add the controller.
409e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
410e41f4b71Sopenharmony_ci              HDF_LOGE("%s: add Pin cntlr: failed", __func__);
411e41f4b71Sopenharmony_ci              ret = HDF_FAILURE;
412e41f4b71Sopenharmony_ci          }
413e41f4b71Sopenharmony_ci          return HDF_SUCCESS;
414e41f4b71Sopenharmony_ci      }
415e41f4b71Sopenharmony_ci      ```
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ci   - Implement the **Release** function.
418e41f4b71Sopenharmony_ci
419e41f4b71Sopenharmony_ci      Input parameters:
420e41f4b71Sopenharmony_ci
421e41f4b71Sopenharmony_ci      **HdfDeviceObject**, a device object created by the HDF for each driver, holds device-related private data and service APIs.
422e41f4b71Sopenharmony_ci
423e41f4b71Sopenharmony_ci      Return value:
424e41f4b71Sopenharmony_ci
425e41f4b71Sopenharmony_ci      No value is returned.
426e41f4b71Sopenharmony_ci
427e41f4b71Sopenharmony_ci      Function description:
428e41f4b71Sopenharmony_ci
429e41f4b71Sopenharmony_ci      Releases the memory and deletes the controller. This function needs to assign values to **Release()** in the driver entry structure. If the HDF fails to call **Init()** to initialize the driver, **Release()** is called to release driver resources.
430e41f4b71Sopenharmony_ci
431e41f4b71Sopenharmony_ci      ```c
432e41f4b71Sopenharmony_ci      static void Hi35xxPinRelease(struct HdfDeviceObject *device)
433e41f4b71Sopenharmony_ci      {
434e41f4b71Sopenharmony_ci          int32_t ret;
435e41f4b71Sopenharmony_ci          uint16_t number;
436e41f4b71Sopenharmony_ci          struct PinCntlr *cntlr = NULL;
437e41f4b71Sopenharmony_ci          struct Hi35xxPinCntlr *hi35xx = NULL;
438e41f4b71Sopenharmony_ci          struct DeviceResourceIface *drsOps = NULL;
439e41f4b71Sopenharmony_ci
440e41f4b71Sopenharmony_ci          if (device == NULL || device->property == NULL) {
441e41f4b71Sopenharmony_ci              HDF_LOGE("%s: device or property is null", __func__);
442e41f4b71Sopenharmony_ci              return;
443e41f4b71Sopenharmony_ci          }
444e41f4b71Sopenharmony_ci          // Read the pin controller number from the .hcs file.
445e41f4b71Sopenharmony_ci          drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
446e41f4b71Sopenharmony_ci          if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {   
447e41f4b71Sopenharmony_ci              HDF_LOGE("%s: invalid drs ops", __func__);
448e41f4b71Sopenharmony_ci              return;
449e41f4b71Sopenharmony_ci          }
450e41f4b71Sopenharmony_ci          ret = drsOps->GetUint16(device->property, "number", &number, 0);
451e41f4b71Sopenharmony_ci          if (ret != HDF_SUCCESS) {
452e41f4b71Sopenharmony_ci              HDF_LOGE("%s: read cntlr number failed", __func__);
453e41f4b71Sopenharmony_ci              return;
454e41f4b71Sopenharmony_ci          }
455e41f4b71Sopenharmony_ci
456e41f4b71Sopenharmony_ci          cntlr = PinCntlrGetByNumber(number);            // Obtain the pin controller based on the controller number. 
457e41f4b71Sopenharmony_ci          PinCntlrRemove(cntlr);
458e41f4b71Sopenharmony_ci          hi35xx = (struct Hi35xxPinCntlr *)cntlr;
459e41f4b71Sopenharmony_ci          if (hi35xx != NULL) {
460e41f4b71Sopenharmony_ci              if (hi35xx->regBase != NULL) {
461e41f4b71Sopenharmony_ci                  OsalIoUnmap((void *)hi35xx->regBase);
462e41f4b71Sopenharmony_ci              }
463e41f4b71Sopenharmony_ci              OsalMemFree(hi35xx);
464e41f4b71Sopenharmony_ci          }
465e41f4b71Sopenharmony_ci      }
466e41f4b71Sopenharmony_ci      ```
467e41f4b71Sopenharmony_ci
468e41f4b71Sopenharmony_ci4. Debug the driver.
469e41f4b71Sopenharmony_ci
470e41f4b71Sopenharmony_ci   (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
471