| doRequest | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmd**: structure pointer to the command to execute.| HDF_STATUS| Processes the request.|
| doRequest | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmd**: structure pointer to the command to execute.| HDF_STATUS| Processes the request.|
| setClock | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**clock**: clock frequency to set.| HDF_STATUS| Sets the clock frequency.|
| setClock | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**clock**: clock frequency to set.| HDF_STATUS| Sets the clock frequency.|
| setPowerMode | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**mode**: power consumption mode, which is an enumerated value.| HDF_STATUS| Sets the power consumption mode.|
| setPowerMode | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**mode**: power consumption mode, which is an enumerated value.| HDF_STATUS| Sets the power consumption mode.|
| setBusWidth | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**width**: bus width, which is an enumerated value.| HDF_STATUS| Sets the bus width.|
| setBusWidth | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**width**: bus width, which is an enumerated value.| HDF_STATUS| Sets the bus width.|
| setBusTiming | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**timing**: bus timing, which is an enumerated value.| HDF_STATUS| Sets the bus timing.|
| setBusTiming | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**timing**: bus timing, which is an enumerated value.| HDF_STATUS| Sets the bus timing.|
| setSdioIrq | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable Secure Digital Input Output (SDIO) interrupts.| HDF_STATUS| Enables or disables SDIO interrupts.|
| setSdioIrq | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable Secure Digital Input Output (SDIO) interrupts.| HDF_STATUS| Enables or disables SDIO interrupts.|
| hardwareReset | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Resets hardware.|
| hardwareReset | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Resets hardware.|
| systemInit | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Performs system initialization.|
| systemInit | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Performs system initialization.|
| setEnhanceSrobe | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable the enhanced strobe feature.| HDF_STATUS| Sets the enhanced strobe feature.|
| setEnhanceSrobe | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**enable**: whether to enable the enhanced strobe feature.| HDF_STATUS| Sets the enhanced strobe feature.|
| switchVoltage | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**volt**: voltage to set, which can be 3.3 V, 1.8 V, or 1.2 V.| HDF_STATUS| Sets the voltage.|
| switchVoltage | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**volt**: voltage to set, which can be 3.3 V, 1.8 V, or 1.2 V.| HDF_STATUS| Sets the voltage.|
| devReadOnly | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is read-only.|
| devReadOnly | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is read-only.|
| cardPluged | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is removed.|
| cardPluged | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is removed.|
| devBusy | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is being used.|
| devBusy | **cntlr**: structure pointer to the MMC controller at the core layer.| Boolean value| Checks whether the device is being used.|
| tune | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmdCode**: command code of the uint32_t type.| HDF_STATUS| Tunes the oscillator circuit frequency.|
| tune | **cntlr**: structure pointer to the MMC controller at the core layer.<br>**cmdCode**: command code of the uint32_t type.| HDF_STATUS| Tunes the oscillator circuit frequency.|
| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.|
| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.|
## How to Develop
## How to Develop
...
@@ -75,6 +75,7 @@ The MMC module adaptation involves the following steps:
...
@@ -75,6 +75,7 @@ The MMC module adaptation involves the following steps:
> For details about the functions in **MmcCntlrOps**, see [Available APIs](#available-apis).
> For details about the functions in **MmcCntlrOps**, see [Available APIs](#available-apis).
4. Debug the driver.
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, for example, check the information returned after the **MmcCntlrOps** instance is attached and whether the device starts successfully.
(Optional) For new drivers, verify the basic functions, for example, check the information returned after the **MmcCntlrOps** instance is attached and whether the device starts successfully.
...
@@ -82,12 +83,14 @@ The MMC module adaptation involves the following steps:
...
@@ -82,12 +83,14 @@ The MMC module adaptation involves the following steps:
The following uses **himci.c** as an example to present the information required for implementing device functions.
The following uses **himci.c** as an example to present the information required for implementing device functions.
1. Instantiate the driver entry.<br/>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.
1. 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.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
MMC driver entry example:
MMC driver entry example:
```
```
struct HdfDriverEntry g_mmcDriverEntry = {
struct HdfDriverEntry g_mmcDriverEntry = {
.moduleVersion = 1,
.moduleVersion = 1,
...
@@ -99,13 +102,15 @@ The following uses **himci.c** as an example to present the information required
...
@@ -99,13 +102,15 @@ The following uses **himci.c** as an example to present the information required
HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **mmc_config.hcs** file.
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **mmc_config.hcs** file.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **MmcCntlr** members at the core layer. If there are multiple devices, you need to add the **deviceNode** information to the **device_info** file and add the device attributes to the **mmc_config** file for each device.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **MmcCntlr** members at the core layer.
If there are multiple devices, you need to add the **deviceNode** information to the **device_info** file and add the device attributes to the **mmc_config** file for each device.
-**device_info.hcs** configuration example
-**device_info.hcs** configuration example
```
```
root {
root {
device_info {
device_info {
...
@@ -118,7 +123,7 @@ The following uses **himci.c** as an example to present the information required
...
@@ -118,7 +123,7 @@ The following uses **himci.c** as an example to present the information required
policy = 2;
policy = 2;
priority = 10;
priority = 10;
permission = 0644;
permission = 0644;
moduleName = "hi3516_mmc_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
moduleName = "hi3516_mmc_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_PLATFORM_MMC_0"; // (Mandatory) Unique name of the service published by the driver.
serviceName = "HDF_PLATFORM_MMC_0"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hi3516_mmc_emmc";// (Mandatory) Private data of the controller. The value must be the same as the controller information in mmc_config.hcs.
deviceMatchAttr = "hi3516_mmc_emmc";// (Mandatory) Private data of the controller. The value must be the same as the controller information in mmc_config.hcs.
}
}
...
@@ -146,12 +151,12 @@ The following uses **himci.c** as an example to present the information required
...
@@ -146,12 +151,12 @@ The following uses **himci.c** as an example to present the information required
-**mmc_config.hcs** configuration example
-**mmc_config.hcs** configuration example
```
```
root {
root {
platform {
platform {
mmc_config {
mmc_config {
template mmc_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
template mmc_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
match_attr = "";
match_attr = "";
voltDef = 0; // 3.3V
voltDef = 0; // 3.3V
freqMin = 50000; // (Mandatory) Minimum frequency
freqMin = 50000; // (Mandatory) Minimum frequency
...
@@ -165,7 +170,7 @@ The following uses **himci.c** as an example to present the information required
...
@@ -165,7 +170,7 @@ The following uses **himci.c** as an example to present the information required
hostId = 0; // (Mandatory) Host ID
hostId = 0; // (Mandatory) Host ID
regBasePhy = 0x10020000;// (Mandatory) Physical base address of the register
regBasePhy = 0x10020000;// (Mandatory) Physical base address of the register
irqNum = 63; // (Mandatory) Interrupt number
irqNum = 63; // (Mandatory) Interrupt number
devType = 2; // (Mandatory) Device type, which can be eMMC, SD, SDIO, or COMBO
devType = 2; // (Mandatory) Device type, which can be eMMC, SD, SDIO, or COMBO.
caps = 0x0001e045; // (Mandatory) Attribute register. For details, see MmcCaps in mmc_caps.h.
caps = 0x0001e045; // (Mandatory) Attribute register. For details, see MmcCaps in mmc_caps.h.
}
}
controller_0x10100000 :: mmc_controller {
controller_0x10100000 :: mmc_controller {
...
@@ -199,11 +204,12 @@ The following uses **himci.c** as an example to present the information required
...
@@ -199,11 +204,12 @@ The following uses **himci.c** as an example to present the information required
```
```
3. Initialize the **MmcCntlr** 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 **MmcCntlrOps** in **MmcCntlr** (so that the underlying driver functions can be called).
3. Initialize the **MmcCntlr** 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 **MmcCntlrOps** in **MmcCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **mmc_config.hcs** file to initialize the members in the custom structure and passes important parameters to the **MmcCntlr** object at the core layer.
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **mmc_config.hcs** file to initialize the members in the custom structure and passes important parameters to the **MmcCntlr** object at the core layer.
@@ -225,7 +231,7 @@ The following uses **himci.c** as an example to present the information required
...
@@ -225,7 +231,7 @@ The following uses **himci.c** as an example to present the information required
bool waitForEvent;
bool waitForEvent;
HIMCI_EVENT himciEvent;
HIMCI_EVENT himciEvent;
};
};
// MmcCntlr is the core layer controller structure. The bind function assigns values to the members of MmcCntlr.
// MmcCntlr is the core layer controller structure. The Bind function assigns values to the members of MmcCntlr.
struct MmcCntlr {
struct MmcCntlr {
struct IDeviceIoService service;
struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
struct HdfDeviceObject *hdfDevObj;
...
@@ -256,7 +262,7 @@ The following uses **himci.c** as an example to present the information required
...
@@ -256,7 +262,7 @@ The following uses **himci.c** as an example to present the information required
- Instantiating **MmcCntlrOps** in **MmcCntlr** (other members are initialized by **Bind**)
- Instantiating **MmcCntlrOps** in **MmcCntlr** (other members are initialized by **Bind**)
```
```
static struct MmcCntlrOps g_himciHostOps = {
static struct MmcCntlrOps g_himciHostOps = {
.request = HimciDoRequest,
.request = HimciDoRequest,
...
@@ -284,22 +290,22 @@ The following uses **himci.c** as an example to present the information required
...
@@ -284,22 +290,22 @@ The following uses **himci.c** as an example to present the information required
**Return value**:
**Return value**:
HDF_STATUS<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
**HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
| HDF_ERR_INVALID_PARAM | Invalid parameter.|
| HDF_ERR_INVALID_PARAM | Invalid parameter.|
| HDF_ERR_IO | I/O error.|
| HDF_ERR_IO | I/O error.|
| HDF_SUCCESS | Initialization successful.|
| HDF_SUCCESS | Initialization successful.|
| HDF_FAILURE | Initialization failed.|
| HDF_FAILURE | Initialization failed.|
**Function description**:
**Function description**:
Initializes the custom structure **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer. **MmcCntlr**, **HimciHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully.
Initializes the custom structure **HimciHost** object and **MmcCntlr**, and calls the **MmcCntlrAdd** function at the core layer. **MmcCntlr**, **HimciHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully.
@@ -374,16 +380,19 @@ The following uses **himci.c** as an example to present the information required
...
@@ -374,16 +380,19 @@ The following uses **himci.c** as an example to present the information required
**Function description**:
**Function description**:
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If 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 value assignment operations.
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If 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 **Init()** has the corresponding value assignment operations.
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to MmcCntlr by using service. For details about the value assignment, see the Bind function.
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to MmcCntlr by using service. For details about the value assignment, see the Bind function.
...
...
HimciDeleteHost((struct HimciHost *)cntlr->priv);// Customized memory release function. A forced conversion from MmcCntlr to HimciHost is involved in the process.
HimciDeleteHost((struct HimciHost *)cntlr->priv);// Customized memory release function. A forced conversion from MmcCntlr to HimciHost is involved in the process.
@@ -20,10 +20,9 @@ Pin, as a software concept, provides APIs for uniformly managing the pins from d
...
@@ -20,10 +20,9 @@ Pin, as a software concept, provides APIs for uniformly managing the pins from d
### Working Principles
### Working Principles
In the HDF, the pin module does not support the user mode and therefore does not need to publish services. It uses the service-free mode in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
In the HDF, the pin module does not support the user mode and therefore does not need to publish services. The pin module uses the service-free mode (as shown in Figure 1) in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
The pin module is divided into the following layers:
The pin module is divided into the following layers:
- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks.
- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks.
- Adaptation layer: instantiates hooks to implement specific functions.
- Adaptation layer: instantiates hooks to implement specific functions.
...
@@ -44,8 +43,7 @@ The pin module is used to manage pin resources. When the devices from SoC vendor
...
@@ -44,8 +43,7 @@ The pin module is used to manage pin resources. When the devices from SoC vendor
### Available APIs
### Available APIs
The **PinCntlrMethod** APIs are used to call the functions of the pin driver.
The **PinCntlrMethod** structure defines callbacks to be invoked to call the functions of the pin driver.
**PinCntlrMethod** definition:
```c
```c
structPinCntlrMethod{
structPinCntlrMethod{
...
@@ -58,7 +56,7 @@ struct PinCntlrMethod {
...
@@ -58,7 +56,7 @@ struct PinCntlrMethod {
};
};
```
```
**Table 1**APIs for the members in the PinCntlrMethod structure
**Table 1**Callbacks in the PinCntlrMethod structure
The pin module adaptation procedure is as follows:
The pin module adaptation procedure is as follows:
- Instantiate the driver entry.
1. Instantiate the driver entry.
- Configure attribute files.
2. Configure attribute files.
- Instantiate the core layer APIs.
3. Instantiate the core layer APIs.
- Debug the driver.
4. Debug the driver.
### Development Example
1. Instantiate the driver entry.
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Instantiate the **HdfDriverEntry** structure.
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**.
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**.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
Generally, the HDF calls the **Init** function to load the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
@@ -92,13 +94,15 @@ The pin module adaptation procedure is as follows:
...
@@ -92,13 +94,15 @@ The pin module adaptation procedure is as follows:
.Bind = Hi35xxPinBind,
.Bind = Hi35xxPinBind,
.Init = Hi35xxPinInit,
.Init = Hi35xxPinInit,
.Release = Hi35xxPinRelease,
.Release = Hi35xxPinRelease,
.moduleName = "hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.moduleName = "hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
};
HDF_INIT(g_hi35xxPinDriverEntry);// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_hi35xxPinDriverEntry);// Call HDF_INIT to register the driver entry with the HDF.
```
```
2. Configure attribute files.
2. Configure attribute files.
- Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
- Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
```c
```c
root {
root {
device_info {
device_info {
...
@@ -106,8 +110,8 @@ The pin module adaptation procedure is as follows:
...
@@ -106,8 +110,8 @@ The pin module adaptation procedure is as follows:
hostName = "platform_host";
hostName = "platform_host";
priority = 50;
priority = 50;
device_pin :: device {
device_pin :: device {
device0::deviceNode{// Set an HDF device node for each pin controller.
device0:: deviceNode { // Set an HDF device node for each pin controller.
policy=0;// 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
policy = 0; // Policy for publishing services.
priority = 10; // Driver startup priority.
priority = 10; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
permission = 0644; // Permission to create device nodes for the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
...
@@ -122,13 +126,14 @@ The pin module adaptation procedure is as follows:
...
@@ -122,13 +126,14 @@ The pin module adaptation procedure is as follows:
moduleName = "hi35xx_pin_driver";
moduleName = "hi35xx_pin_driver";
deviceMatchAttr = "hisilicon_hi35xx_pin_1";
deviceMatchAttr = "hisilicon_hi35xx_pin_1";
}
}
......
...
}
}
}
}
}
}
}
}
```
```
- Add the **pin_config.hcs** file.
- Add the **pin_config.hcs** file.
Configure the device attributes in the **device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs** file. The parameters are set as follows:
Configure the device attributes in the **device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs** file. The parameters are set as follows:
```c
```c
root {
root {
...
@@ -137,12 +142,12 @@ The pin module adaptation procedure is as follows:
...
@@ -137,12 +142,12 @@ The pin module adaptation procedure is as follows:
template pin_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
template pin_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
number = 0; // (Mandatory) Controller ID.
number = 0; // (Mandatory) Controller ID.
regStartBasePhy = 0; // (Mandatory) Start physical base address of the register.
regStartBasePhy = 0; // (Mandatory) Start physical base address of the register.
regSize=0;// (Mandatory) Register bit width.
regSize = 0; // (Mandatory) Register bit width.
PinCount = 0; // (Mandatory) Number of pins.
PinCount = 0; // (Mandatory) Number of pins.
match_attr = "";
match_attr = "";
template pin_desc {
template pin_desc {
pinName = ""; // (Mandatory) Name of the pin.
pinName = ""; // (Mandatory) Name of the pin.
init=0;// (Mandatory) Default value of the register.
init = 0; // (Mandatory) Default value of the register.
F0 = ""; // (Mandatory) Function 0.
F0 = ""; // (Mandatory) Function 0.
F1 = ""; // Function 1.
F1 = ""; // Function 1.
F2 = ""; // Function 2.
F2 = ""; // Function 2.
...
@@ -164,16 +169,18 @@ The pin module adaptation procedure is as follows:
...
@@ -164,16 +169,18 @@ The pin module adaptation procedure is as follows:
F1 = "SFC_CLK";
F1 = "SFC_CLK";
F2 = "SFC_BOOT_MODE";
F2 = "SFC_BOOT_MODE";
}
}
......// Correspond to the pins of the pin controller. Add pins according to actual situation.
... // Correspond to the pins of the pin controller. Add pins according to actual situation.
}
}
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
}
}
}
}
}
}
```
```
3. Instantiate the pin controller object.
3. Instantiate the pin controller object.
- Initialize the **PinCntlr** object.
- Initialize the **PinCntlr** object.
Call **Hi35xxPinCntlrInit** to initialize the **PinCntlr** members.
Call **Hi35xxPinCntlrInit** to initialize the **PinCntlr** members.
```c
```c
...
@@ -209,14 +216,14 @@ The pin module adaptation procedure is as follows:
...
@@ -209,14 +216,14 @@ The pin module adaptation procedure is as follows:
uint32_t pinCount;
uint32_t pinCount;
};
};
// PinCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init() function.
// PinCntlr is the controller structure at the core layer. The Init function assigns values to PinCntlr.
struct PinCntlr {
struct PinCntlr {
struct IDeviceIoService service;
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct HdfDeviceObject *device;
struct PinCntlrMethod *method;
struct PinCntlrMethod *method;
struct DListHead node; // Node in the linked list.
struct DListHead node; // Node in the linked list.
OsalSpinlock spin; // Spinlock.
OsalSpinlock spin; // Spinlock.
uint16_t number; // ID of the pin controller.
uint16_t number; // ID of the pin controller.
uint16_t pinCount; // Number of pins.
uint16_t pinCount; // Number of pins.
struct PinDesc *pins;
struct PinDesc *pins;
void *priv; // Private data.
void *priv; // Private data.
...
@@ -268,29 +275,31 @@ The pin module adaptation procedure is as follows:
...
@@ -268,29 +275,31 @@ The pin module adaptation procedure is as follows:
}
}
```
```
- Instantiate the callback structure **PinCntlrMethod** in **PinCntlr**. Other members are initialized by using the **Init()** function.
- Instantiate the callback structure **PinCntlrMethod** in **PinCntlr**. Other members are initialized by using the **Init** function.
```c
```c
// The members of the PinCntlrMethod structure are all callbacks. Vendors need to implement the corresponding functions according to Table 1.
// The members of the PinCntlrMethod structure are all callbacks. Vendors need to implement the corresponding functions according to Table 1.
static struct PinCntlrMethod g_method = {
static struct PinCntlrMethod g_method = {
.SetPinPull = Hi35xxPinSetPull, // Set the pull type.
.SetPinPull = Hi35xxPinSetPull, // Set the pull type.
.GetPinPull = Hi35xxPinGetPull, // Obtains the pull type.
.GetPinPull = Hi35xxPinGetPull, // Obtain the pull type.
.SetPinStrength = Hi35xxPinSetStrength, // Set the pull strength.
.SetPinStrength = Hi35xxPinSetStrength, // Set the pull strength.
.GetPinStrength = Hi35xxPinGetStrength, // Obtains the pull strength.
.GetPinStrength = Hi35xxPinGetStrength, // Obtain the pull strength.
.SetPinFunc = Hi35xxPinSetFunc, // Set the pin functions.
.SetPinFunc = Hi35xxPinSetFunc, // Set the pin functions.
.GetPinFunc = Hi35xxPinGetFunc, // Obtain the pin functions.
.GetPinFunc = Hi35xxPinGetFunc, // Obtain the pin functions.
};
};
```
```
-**Init()** function
-**Init** function
**Input parameter**:
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
**HDF\_STATUS** <br>The table below describes some status. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.
@@ -375,19 +385,19 @@ The pin module adaptation procedure is as follows:
...
@@ -375,19 +385,19 @@ The pin module adaptation procedure is as follows:
}
}
```
```
-**Release()** function
-**Release** function
Input parameters:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
–
No value is returned.
Function description:
**Function description**:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources.
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, **Release** can be called to release driver resources.
@@ -426,4 +436,5 @@ The pin module adaptation procedure is as follows:
...
@@ -426,4 +436,5 @@ The pin module adaptation procedure is as follows:
}
}
```
```
4. Debug the driver.
4. Debug the driver.
(Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
(Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
| setConfig | -**pwm**: structure pointer to the PWM controller at the core layer.<br>-**config**: structure pointer to the attributes to set.| HDF_STATUS| Sets attributes.|
| setConfig | **pwm**: structure pointer to the PWM controller at the core layer.<br>**config**: structure pointer to the attributes to set.| HDF_STATUS| Sets attributes.|
| open | **pwm**: structure pointer to the PWM controller at the core layer.| HDF_STATUS| Opens a device.|
| open | **pwm**: structure pointer to the PWM controller at the core layer.| HDF_STATUS| Opens a device.|
| close | **pwm**: structure pointer to the PWM controller at the core layer.| HDF_STATUS| Closes a device.|
| close | **pwm**: structure pointer to the PWM controller at the core layer.| HDF_STATUS| Closes a device.|
## How to Develop
## How to Develop
...
@@ -51,6 +51,7 @@ The PWM module adaptation involves the following steps:
...
@@ -51,6 +51,7 @@ The PWM module adaptation involves the following steps:
> For details about the functions in **PwmMethod**, see [Available APIs](#available-apis).
> For details about the functions in **PwmMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, such as the PWM status control and response to interrupts.
(Optional) For new drivers, verify the basic functions, such as the PWM status control and response to interrupts.
...
@@ -58,12 +59,16 @@ The PWM module adaptation involves the following steps:
...
@@ -58,12 +59,16 @@ The PWM module adaptation involves the following steps:
The following uses **pwm_hi35xx.c** as an example to present the information required for implementing device functions.
The following uses **pwm_hi35xx.c** as an example to present the information required for implementing device functions.
1. Instantiate the driver entry.<br/>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.
1. 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.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
PWM driver entry example:
PWM driver entry example:
```
```
struct HdfDriverEntry g_hdfPwm = {
struct HdfDriverEntry g_hdfPwm = {
.moduleVersion = 1,
.moduleVersion = 1,
...
@@ -76,23 +81,26 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -76,23 +81,26 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
HDF_INIT(g_hdfPwm);
HDF_INIT(g_hdfPwm);
```
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **pwm_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **PwmDev** members at the core layer. If there are multiple devices, you need to add the **deviceNode** information to the **device_info** file and add the device attributes to the **pwm_config** file for each device.
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **pwm_config.hcs** file.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **PwmDev** members at the core layer. If there are multiple devices, you need to add the **deviceNode** information to the **device_info** file and add the device attributes to the **pwm_config** file for each device.
-**device_info.hcs** configuration example
-**device_info.hcs** configuration example
```
```
root {
root {
device_info {
device_info {
platform :: host {
platform :: host {
hostName = "platform_host";
hostName = "platform_host";
priority = 50;
priority = 50;
device_pwm :: device {// Configure an HDF device node for each PWM controller.
device_pwm :: device {// Configure an HDF device node for each PWM controller.
device0 :: deviceNode {
device0 :: deviceNode {
policy = 1; // Publish kernel-mode services.
policy = 1; // Publish services for kernel-mode processes.
priority = 80; // Driver startup priority
priority = 80; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
permission = 0644; // Permission for the driver to create a device node.
moduleName = "HDF_PLATFORM_PWM"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
moduleName = "HDF_PLATFORM_PWM"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_PLATFORM_PWM_0"; // (Mandatory) Unique name of the service published by the driver.
serviceName = "HDF_PLATFORM_PWM_0"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hisilicon_hi35xx_pwm_0";// (Mandatory) Used to configure the private data of the controller.
deviceMatchAttr = "hisilicon_hi35xx_pwm_0";// (Mandatory) Used to configure the private data of the controller.
// The value must be the same as the controller information in pwm_config.hcs.
// The value must be the same as the controller information in pwm_config.hcs.
}
}
...
@@ -111,7 +119,7 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -111,7 +119,7 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
```
```
-**pwm_config.hcs** configuration example
-**pwm_config.hcs** configuration example
```
```
root {
root {
platform {
platform {
...
@@ -135,12 +143,13 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -135,12 +143,13 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
}
}
```
```
3. Initialize the **PwmDev** 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 **PwmMethod** in **PwmDev** (so that the underlying driver functions can be called).
3. Initialize the **wmDev** 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 **PwmMethod** in **PwmDev** (so that the underlying driver functions can be called).
- Defining a custom structure
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **pwm_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number, to the **GpioCntlr** object at the core layer.
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **pwm_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number, to the object at the core layer.
@@ -154,14 +163,14 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -154,14 +163,14 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
struct IDeviceIoService service;
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct HdfDeviceObject *device;
struct PwmConfig cfg; // Attribute structure. For details, see the description of PwmConfig.
struct PwmConfig cfg; // Attribute structure. For details, see the description of PwmConfig.
struct PwmMethod *method; // Hook function template
struct PwmMethod *method; // Hook function template
bool busy;
bool busy;
uint32_t num; // Device number
uint32_t num; // Device number
OsalSpinlock lock;
OsalSpinlock lock;
void *priv; // Private data. Generally, the start address of the custom structure is stored to facilitate invoking of the structure.
void *priv; // Private data. Generally, the start address of the custom structure is stored to facilitate invoking of the structure.
};
};
struct PwmConfig {
struct PwmConfig {
uint32_t duty // Time that a signal is in the ON state, in ns.
uint32_t duty // Time that a signal is in the ON state, in ns.
uint32_t period; // Time for a signal to complete an on-and-off cycle, in ns.
uint32_t period; // Time for a signal to complete an on-and-off cycle, in ns.
uint32_t number; // Number of square waves to generate.
uint32_t number; // Number of square waves to generate.
uint8_t polarity; // Polarity
uint8_t polarity; // Polarity
...
@@ -178,7 +187,7 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -178,7 +187,7 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
- Instantiating **PwmMethod** in **PwmDev** (other members are initialized by **Init**)
- Instantiating **PwmMethod** in **PwmDev** (other members are initialized by **Init**)
```
```
// The following uses pwm_hi35xx.c as an example. Fill the hook function.
// The following uses pwm_hi35xx.c as an example. Fill the hook function.
struct PwmMethod g_pwmOps = {
struct PwmMethod g_pwmOps = {
...
@@ -193,24 +202,24 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -193,24 +202,24 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
**Return value**:
**Return value**:
HDF_STATUS<br>The table below lists some status. For more information, see HDF_STATUS in the /drivers/framework/include/utils/hdf_base.h file.
**HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
if (PwmDeviceAdd(obj, &(hp->dev)) ) != HDF_SUCCESS) {// (Important) Call the core layer function to initialize hp->dev devices and services.
if (PwmDeviceAdd(obj, &(hp->dev)) ) != HDF_SUCCESS) { // Call the core layer function to initialize devices and services.
OsalIoUnmap((void *)hp->base);
OsalIoUnmap((void *)hp->base);
return HDF_FAILURE;
return HDF_FAILURE;
}
}
...
@@ -267,7 +276,7 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
...
@@ -267,7 +276,7 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
@@ -16,7 +16,7 @@ The regulator module is divided into the following layers:
...
@@ -16,7 +16,7 @@ The regulator module is divided into the following layers:
- Core layer: provides the capabilities of binding, initializing, and releasing devices.
- Core layer: provides the capabilities of binding, initializing, and releasing devices.
- Adaptation layer: implements other functions.
- Adaptation layer: implements other functions.
![](../public_sys-resources/icon-note.gif)NOTE<br/>The core layer can call the APIs of the interface layer and uses hooks to call APIs of the adaptation layer. In this way, the adaptation layer can indirectly call the APIs of the interface layer, but the interface layer cannot call the APIs of the adaptation layer.
![](../public_sys-resources/icon-note.gif)**NOTE**<br/>The core layer can call the APIs of the interface layer and uses hooks to call APIs of the adaptation layer. In this way, the adaptation layer can indirectly call the APIs of the interface layer, but the interface layer cannot call the APIs of the adaptation layer.
**Figure 1** Unified service mode
**Figure 1** Unified service mode
...
@@ -28,12 +28,13 @@ The regulator module is divided into the following layers:
...
@@ -28,12 +28,13 @@ The regulator module is divided into the following layers:
Currently, the regulator module supports only the kernels (LiteOS) of mini and small systems.
Currently, the regulator module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
### When to Use
The regulator module controls the voltage and current supplies of some devices in the system.
The regulator module controls the voltage and current supplies of some devices in the system.
## Available APIs
### Available APIs
The functions in **RegulatorMethod** are used to call the corresponding regulator driver functions:
The functions in **RegulatorMethod** are used to call the corresponding regulator driver functions:
...
@@ -72,8 +73,7 @@ struct RegulatorMethod {
...
@@ -72,8 +73,7 @@ struct RegulatorMethod {
| getCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current. |
| getCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current. |
| getStatus | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status. |
| getStatus | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status. |
### How to Develop
## How to Develop
The regulator module adaptation procedure is as follows:
The regulator module adaptation procedure is as follows:
...
@@ -86,9 +86,11 @@ The regulator module adaptation procedure is as follows:
...
@@ -86,9 +86,11 @@ The regulator module adaptation procedure is as follows:
1. Instantiate the driver entry.
1. 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.
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.
Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release** to release driver resources and exit.
Generally, the HDF calls the **Init** function to load the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
```
```
struct HdfDriverEntry g_regulatorDriverEntry = {
struct HdfDriverEntry g_regulatorDriverEntry = {
...
@@ -116,7 +118,7 @@ The regulator module adaptation procedure is as follows:
...
@@ -116,7 +118,7 @@ The regulator module adaptation procedure is as follows:
Configure regulator controller information from the second node. This node specifies a type of regulator controllers rather than a specific regulator controller. In this example, there is only one regulator device. If there are multiple regulator devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **regulator\_config** file.
Configure regulator controller information from the second node. This node specifies a type of regulator controllers rather than a specific regulator controller. In this example, there is only one regulator device. If there are multiple regulator devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **regulator\_config** file.
...
@@ -131,7 +133,7 @@ The regulator module adaptation procedure is as follows:
...
@@ -131,7 +133,7 @@ The regulator module adaptation procedure is as follows:
device_regulator :: device {
device_regulator :: device {
device0:: deviceNode { // Set an HDF device node for each regulator controller.
device0:: deviceNode { // Set an HDF device node for each regulator controller.
policy = 1; // Policy for the driver to publish services.
policy = 1; // Policy for the driver to publish services.
priority = 50; // Driver startup priority.
priority = 50; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
permission = 0644; // Permission to create device nodes for the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
...
@@ -198,7 +200,7 @@ The regulator module adaptation procedure is as follows:
...
@@ -198,7 +200,7 @@ The regulator module adaptation procedure is as follows:
}
}
```
```
3. Instantiate the APIs of the core layer.
3. Instantiate the core layer APIs.
Initialize the **RegulatorNode** 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 **RegulatorMethod** in **RegulatorNode** (so that the underlying driver functions can be called).
Initialize the **RegulatorNode** 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 **RegulatorMethod** in **RegulatorNode** (so that the underlying driver functions can be called).
...
@@ -206,8 +208,6 @@ The regulator module adaptation procedure is as follows:
...
@@ -206,8 +208,6 @@ The regulator module adaptation procedure is as follows:
The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator_config.hcs** using **DeviceResourceIface**.
The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator_config.hcs** using **DeviceResourceIface**.
```
```
// RegulatorNode is the core layer controller structure. The Init function assigns values to the members of RegulatorNode.
// RegulatorNode is the core layer controller structure. The Init function assigns values to the members of RegulatorNode.
struct RegulatorNode {
struct RegulatorNode {
...
@@ -219,17 +219,17 @@ The regulator module adaptation procedure is as follows:
...
@@ -219,17 +219,17 @@ The regulator module adaptation procedure is as follows:
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
| HDF_ERR_INVALID_PARAM | Invalid parameter. |
| HDF_ERR_IO | I/O error. |
| HDF_SUCCESS | Initialization successful. |
| HDF_FAILURE | Initialization failed. |
Function description:
Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer.
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
| HDF_ERR_INVALID_PARAM | Invalid parameter. |
| HDF_ERR_IO | I/O error. |
| HDF_SUCCESS | Initialization successful. |
| HDF_FAILURE | Initialization failed. |
**Function description**:
Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer.
regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));// Load the .hcs file.
...
ret = VirtualRegulatorReadHcs(regNode, node); // Read .hcs information.
...
regNode->priv = (void *)node; ; // Instantiate the node.
regNode->ops = &g_method; // Instantiate OPS.
ret = RegulatorNodeAdd(regNode); // Add the node.
...
}
```
-**Release** function
-**Release** function
Input parameter:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
No value is return.
No value is returned.
Function description:
**Function description**:
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
> For details about the functions in **SpiCntlrMethod**, see [Available APIs](#available-apis).
> For details about the functions in **SpiCntlrMethod**, see [Available APIs](#available-apis).
4. Debug the driver.<br>
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, such as the SPI status control and response to interrupts.
(Optional) For new drivers, verify the basic functions, such as the SPI status control and response to interrupts.
...
@@ -61,10 +62,15 @@ The SPI module adaptation involves the following steps:
...
@@ -61,10 +62,15 @@ The SPI module adaptation involves the following steps:
The following uses **spi_hi35xx.c** as an example to present the information required for implementing device functions.
The following uses **spi_hi35xx.c** as an example to present the information required for implementing device functions.
1. Instantiate the driver entry.<br/>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 framework, 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.
1. 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.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
SPI driver entry example:
SPI driver entry example:
```
```
struct HdfDriverEntry g_hdfSpiDevice = {
struct HdfDriverEntry g_hdfSpiDevice = {
...
@@ -78,12 +84,12 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -78,12 +84,12 @@ The following uses **spi_hi35xx.c** as an example to present the information req
HDF_INIT(g_hdfSpiDevice);
HDF_INIT(g_hdfSpiDevice);
```
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **spi_config.hcs** file.
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **spi_config.hcs** file.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **SpiCntlr** members at the core layer.
The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the default values or value ranges of the **SpiCntlr** members at the core layer.
In this example, there is only one SPI controller. If there are multiple SPI controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **spi_config** file for each controller.
In this example, there is only one SPI controller. If there are multiple SPI controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **spi_config** file for each controller.
-**device_info.hcs** configuration example
-**device_info.hcs** configuration example
...
@@ -124,22 +130,22 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -124,22 +130,22 @@ The following uses **spi_hi35xx.c** as an example to present the information req
```
```
root {
root {
platform {
platform {
spi_config {// Configure private data for each SPI controller.
spi_config {// Configure private data for each SPI controller.
template spi_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
template spi_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
serviceName = "";
serviceName = "";
match_attr = "";
match_attr = "";
transferMode = 0; // Data transfer mode. The value **0** indicates interrupt transfer, **1** indicates flow control transfer, and **2** indicates DMA transfer.
transferMode = 0; // Data transfer mode. The value **0** indicates interrupt transfer, **1** indicates flow control transfer, and **2** indicates DMA transfer.
busNum = 0; // Bus number.
busNum = 0; // Bus number.
clkRate = 100000000;
clkRate = 100000000;
bitsPerWord = 8 // Number of bits per word.
bitsPerWord = 8; // Number of bits per word.
mode = 19; // SPI data input/output mode.
mode = 19; // SPI data input/output mode.
maxSpeedHz = 0; // Maximum clock frequency.
maxSpeedHz = 0; // Maximum clock frequency.
minSpeedHz = 0; // Minimum clock frequency.
minSpeedHz = 0; // Minimum clock frequency.
speed = 2000000; // Current message transfer speed.
speed = 2000000; // Current message transfer speed.
fifoSize = 256; // FIFO size.
fifoSize = 256; // FIFO size.
numCs = 1; // Chip select (CS) number.
numCs = 1; // Chip select (CS) number.
regBase = 0x120c0000; // Used for address mapping.
regBase = 0x120c0000; // Used for address mapping.
match_attr = "hisilicon_hi35xx_spi_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
match_attr = "hisilicon_hi35xx_spi_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
}
}
controller_0x120c1000 :: spi_controller {
controller_0x120c1000 :: spi_controller {
...
@@ -163,17 +169,18 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -163,17 +169,18 @@ The following uses **spi_hi35xx.c** as an example to present the information req
}
}
...
...
//(Optional) Add nodes to the device_info.hcs file as required.
//(Optional) Add nodes to the device_info.hcs file as required.
}
}
}
}
}
}
```
```
3. Initialize the **SpiCntlr** 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 **SpiCntlrMethod** in **SpiCntlr** (so that the underlying driver functions can be called).
3. Initialize the **SpiCntlr** 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 **SpiCntlrMethod** in **SpiCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **spi_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number and bus number, to the **SpiCntlr** object at the core layer.
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface** method provided by the HDF reads the values in the **spi_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number and bus number, to the **SpiCntlr** object at the core layer.
```
```
struct Pl022 {// Corresponds to parameters in .hcs.
struct Pl022 {// Corresponds to parameters in .hcs.
struct SpiCntlr *cntlr;
struct SpiCntlr *cntlr;
...
@@ -231,15 +238,15 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -231,15 +238,15 @@ The following uses **spi_hi35xx.c** as an example to present the information req
-**Bind** function
-**Bind** function
Input parameter:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
HDF_STATUS
**HDF_STATUS**
Function description:
**Function description**:
Associates the **SpiCntlr** object with **HdfDeviceObject**.
Associates the **SpiCntlr** object with **HdfDeviceObject**.
...
@@ -253,14 +260,14 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -253,14 +260,14 @@ The following uses **spi_hi35xx.c** as an example to present the information req
cntlr->device = device; // Prerequisites for conversion between HdfDeviceObject and SpiCntlr.
cntlr->device = device; // Prerequisites for conversion between HdfDeviceObject and SpiCntlr.
device->service = &(cntlr->service); // Prerequisites for conversion between HdfDeviceObject and SpiCntlr.
device->service = &(cntlr->service); // Prerequisites for conversion between HdfDeviceObject and SpiCntlr.
(void)OsalMutexInit(&cntlr->lock); // Initialize the lock.
(void)OsalMutexInit(&cntlr->lock); // Initialize the lock.
DListHeadInit(&cntlr->list); // Add the corresponding nodes.
DListHeadInit(&cntlr->list); // Add nodes.
cntlr->priv = NULL;
cntlr->priv = NULL;
return cntlr;
return cntlr;
}
}
...
@@ -268,17 +275,15 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -268,17 +275,15 @@ The following uses **spi_hi35xx.c** as an example to present the information req
-**Init** function
-**Init** function
Input parameter:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
HDF_STATUS
**HDF_STATUS**<br/>The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
The table below lists some status. For more information, see **HDF_STATUS** in the /drivers/framework/include/utils/hdf_base.h file.
**Table 2** Description of HDF_STATUS
**Table 2** HDF_STATUS
| Status| Description|
| Status| Description|
| -------- | -------- |
| -------- | -------- |
...
@@ -289,10 +294,10 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -289,10 +294,10 @@ The following uses **spi_hi35xx.c** as an example to present the information req
| HDF_SUCCESS | Initialization successful.|
| HDF_SUCCESS | Initialization successful.|
| HDF_FAILURE | Initialization failed.|
| HDF_FAILURE | Initialization failed.|
Function description:
**Function description**:
Initializes the custom structure object and **SpiCntlr**.
Initializes the custom structure object and **SpiCntlr**.
@@ -300,10 +305,10 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -300,10 +305,10 @@ The following uses **spi_hi35xx.c** as an example to present the information req
int32_t ret;
int32_t ret;
struct SpiCntlr *cntlr = NULL;
struct SpiCntlr *cntlr = NULL;
...
...
cntlr = SpiCntlrFromDevice(device); // Use service to forcibly convert HdfDeviceObject to SpiCntlr. For details about the value assignment, see the Bind function.
cntlr = SpiCntlrFromDevice(device); // Forcibly convert HdfDeviceObject to SpiCntlr using service. For details about the value assignment, see the Bind function.
@@ -338,20 +343,22 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -338,20 +343,22 @@ The following uses **spi_hi35xx.c** as an example to present the information req
return 0;
return 0;
}
}
```
```
-**Release** function
-**Release** function
Input parameter:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
No value is returned.
No value is returned.
Function description:
**Function description**:
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If 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 value assignment operations.
> All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations.
```
```
...
@@ -359,8 +366,8 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
@@ -359,8 +366,8 @@ The following uses **spi_hi35xx.c** as an example to present the information req
{
{
struct SpiCntlr *cntlr = NULL;
struct SpiCntlr *cntlr = NULL;
...
...
cntlr = SpiCntlrFromDevice(device); // Use service to forcibly convert HdfDeviceObject to SpiCntlr. For details about the value assignment, see the Bind function.
cntlr = SpiCntlrFromDevice(device); // Forced conversion from HdfDeviceObject to SpiCntlr is involved. For details about the value assignment, see the Bind function.