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 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