提交 a2c3a4e6 编写于 作者: A Annie_wang

update docs

Signed-off-by: NAnnie_wang <annie.wangli@huawei.com>
上级 e52505dc
......@@ -14,7 +14,7 @@ The Display Serial Interface (DSI) is a specification developed by the Mobile In
**MipiDsiCntlrMethod**:
```
struct MipiDsiCntlrMethod { // Member functions of the core layer structure
int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr);
......@@ -22,36 +22,36 @@ struct MipiDsiCntlrMethod { // Member functions of the core layer structure
int32_t (*getCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd, uint32_t readLen, uint8_t *out);
void (*toHs)(struct MipiDsiCntlr *cntlr);
void (*toLp)(struct MipiDsiCntlr *cntlr);
void (*enterUlps)(struct MipiDsiCntlr *cntlr);// (Optional) Enter the Ultra-Low Power State (ULPS).
void (*exitUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Exit the ULPS.
void (*enterUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Enter the Ultra-Low Power State (ULPS).
void (*exitUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Exit the ULPS.
int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable);// (Optional) Enable or disable power control.
int32_t (*attach)(struct MipiDsiCntlr *cntlr);// (Optional) Attach a DSI device to the host.
int32_t (*attach)(struct MipiDsiCntlr *cntlr); // (Optional) Attach a DSI device to the host.
};
```
**Table 1** Description of the callback functions in MipiDsiCntlrMethod
| Function| Input Parameter| Output Parameter| Return Value| Description|
| Function| Input Parameter| Output Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| setCntlrCfg | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets controller parameters.|
| setCmd | **cntlr**: structure pointer to the MIPI DSI controller.<br>cmd: structure pointer to the commands to send.| –| HDF_STATUS| Sends commands to a display device.|
| getCmd | **cntlr**: structure pointer to the MIPI DSI controller.<br>**cmd**: pointer to the command description structure.<br>**readLen**: length of the data to read.| **out**: structure pointer to the data obtained.| HDF_STATUS| Reads data by sending commands.|
| toHs | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets the high speed (HS) mode.|
| toLp | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets the low power (LP) mode.|
| setCntlrCfg | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets controller parameters.|
| setCmd | **cntlr**: structure pointer to the MIPI DSI controller.<br>**cmd**: structure pointer to the commands to send. | –| HDF_STATUS| Sends commands to a display device.|
| getCmd | **cntlr**: structure pointer to the MIPI DSI controller.<br>**cmd**: pointer to the command description structure.<br>**readLen**: length of the data to read.| **out**: structure pointer to the data obtained.| HDF_STATUS| Reads data by sending commands.|
| toHs | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets the high speed (HS) mode.|
| toLp | **cntlr**: structure pointer to the MIPI DSI controller.| –| HDF_STATUS| Sets the low power (LP) mode.|
## How to Develop
The MIPI DSI module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
1. Configure attribute files.
- Add the **deviceNode** description to the **device_info.hcs** file.
- (Optional) Add the **mipidsi_config.hcs** file.
2. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
3. Instantiate the MIPI DSI controller object.
- Initialize **MipiDsiCntlr**.
- Instantiate **MipiDsiCntlrMethod** in the **MipiDsiCntlr** object.
......@@ -59,6 +59,7 @@ The MIPI DSI module adaptation involves the following steps:
> For details about the functions in **MipiDsiCntlrMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
(Optional) For new drivers, verify basic functions, for example, check the information returned after the driver is attached and whether data is successfully transmitted.
......@@ -66,12 +67,14 @@ The MIPI DSI module adaptation involves the following steps:
The following uses **mipi_tx_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
1. Configure the device attributes in **xx_config.hcs** and add the **deviceNode** information to the **device_info.hcs** file. <br>The device attribute values are closely related to the default values or value range of the **MipiDsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
1. Configure the device attributes in **xx_config.hcs** and add the **deviceNode** information to the **device_info.hcs** file.
The device attribute values are closely related to the default values or value range of the **MipiDsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
In this example, no additional attribute needs to be configured for the MIPI DSI controller. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device_info** file and add the **mipidsi_config** file.
**device_info.hcs** configuration example:
```
root {
device_info {
......@@ -84,7 +87,7 @@ The following uses **mipi_tx_hi35xx.c** as an example to present the contents th
policy = 0;
priority = 150;
permission = 0644;
moduleName = "HDF_MIPI_TX"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
moduleName = "HDF_MIPI_TX"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_MIPI_TX"; // (Mandatory) Unique name of the service published by the driver.
}
}
......@@ -93,148 +96,158 @@ The following uses **mipi_tx_hi35xx.c** as an example to present the contents th
}
```
2. 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**. The function pointer members in the **HdfDriverEntry** structure are filled by the vendors' operation functions. 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.
2. 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**. The function pointer members in the **HdfDriverEntry** structure are filled by the vendors' operation functions. 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.
- MIPI DSI driver entry example
MIPI DSI driver entry example:
```
struct HdfDriverEntry g_mipiTxDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxMipiTxInit, // See the Init function.
.Init = Hi35xxMipiTxInit, // See the Init function.
.Release = Hi35xxMipiTxRelease, // See the Release function.
.moduleName = "HDF_MIPI_TX", // (Mandatory) The value must be the same as that in the device_info.hcs file.
.moduleName = "HDF_MIPI_TX", // (Mandatory) The value must be the same as that in the device_info.hcs file.
};
HDF_INIT(g_mipiTxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_mipiTxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
3. Initialize the **MipiDsiCntlr** 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 **MipiDsiCntlrMethod** in **MipiDsiCntlr** (so that the underlying driver functions can be called).
- Defining a custom structure
To the driver, the custom structure holds parameters and data. Generally, the values in the **config** file are used to initialize the structure members. However, in this example, the MIPI DSI has no device attribute file. Therefore, the basic member structure is similar to that of **MipiDsiCntlr**.
To the driver, the custom structure holds parameters and data. Generally, the values in the **config** file are used to initialize the structure members. However, in this example, the MIPI DSI has no device attribute file. Therefore, the basic member structure is similar to that of **MipiDsiCntlr**.
```
typedef struct {
unsigned int devno; // Device number
short laneId[LANE_MAX_NUM]; // Lane ID
OutPutModeTag outputMode; // Output mode, which can be CSI mode, DSI Video mode, or DSI Command mode.
VideoModeTag videoMode; // Synchronization mode of the display device
OutputFormatTag outputFormat; // Format of the output DSI image, which can be RGB or YUV.
SyncInfoTag syncInfo; // Settings related to timing
unsigned int phyDataRate; // Data rate, in Mbit/s
unsigned int pixelClk; // Clock, in kHz
} ComboDevCfgTag;
// MipiDsiCntlr is the controller structure at the core layer. The Init function assigns values to the members of MipiDsiCntlr.
struct MipiDsiCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
unsigned int devNo; // Device number
struct MipiCfg cfg;
struct MipiDsiCntlrMethod *ops;
struct OsalMutex lock;
void *priv;
};
```
```
typedef struct {
unsigned int devno; // Device number
short laneId[LANE_MAX_NUM]; // Lane ID
OutPutModeTag outputMode; // Output mode, which can be CSI mode, DSI Video mode, or DSI Command mode.
VideoModeTag videoMode; // Synchronization mode of the display device
OutputFormatTag outputFormat; // Format of the output DSI image, which can be RGB or YUV.
SyncInfoTag syncInfo; // Settings related to timing
unsigned int phyDataRate; // Data rate, in Mbit/s
unsigned int pixelClk; // Clock, in kHz
} ComboDevCfgTag;
// MipiDsiCntlr is the controller structure at the core layer. The Init function assigns values to the members of MipiDsiCntlr.
struct MipiDsiCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
unsigned int devNo; // Device number
struct MipiCfg cfg;
struct MipiDsiCntlrMethod *ops;
struct OsalMutex lock;
void *priv;
};
```
- Instantiating **MipiDsiCntlrMethod** in **MipiDsiCntlr** (other members are initialized by **Init**)
```
static struct MipiDsiCntlrMethod g_method = {
.setCntlrCfg = Hi35xxSetCntlrCfg,
.setCmd = Hi35xxSetCmd,
.getCmd = Hi35xxGetCmd,
.toHs = Hi35xxToHs,
.toLp = Hi35xxToLp,
};
```
```
static struct MipiDsiCntlrMethod g_method = {
.setCntlrCfg = Hi35xxSetCntlrCfg,
.setCmd = Hi35xxSetCmd,
.getCmd = Hi35xxGetCmd,
.toHs = Hi35xxToHs,
.toLp = Hi35xxToLp,
};
```
- **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<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**
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid object.|
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory.|
| HDF_ERR_INVALID_PARAM | Invalid parameter.|
| HDF_ERR_IO | I/O error.|
| HDF_SUCCESS | Operation successful.|
| HDF_FAILURE | Operation failed.|
The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
**Function description**:
| Status | Description |
| ---------------------- | -------------------------- |
| HDF_ERR_INVALID_OBJECT | Invalid object. |
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
| HDF_ERR_INVALID_PARAM | Invalid parameter. |
| HDF_ERR_IO | I/O error. |
| HDF_SUCCESS | Operation successful. |
| HDF_FAILURE | Operation failed. |
Attaches the **MipiDsiCntlrMethod** instance, calls **MipiDsiRegisterCntlr**, and performs other vendor-defined initialization operations.
**Function description**:
Attaches the **MipiDsiCntlrMethod** instance, calls **MipiDsiRegisterCntlr**, and performs other vendor-defined initialization operations.
```
static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device)
{
int32_t ret;
g_mipiTx.priv = NULL; // g_mipiTx is a global variable defined.
// static struct MipiDsiCntlr g_mipiTx {
// .devNo=0
//};
g_mipiTx.ops = &g_method; // Attach the MipiDsiCntlrMethod instance.
ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
...
return MipiTxDrvInit(0); // (Mandatory) Device initialization customized by the vendor.
}
// mipi_dsi_core.c file
int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr, struct HdfDeviceObject *device)
{
...
// Define the global variable static struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT].
if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) {
(void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock);
(void)OsalMutexInit(&(cntlr->lock));
g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;// Initialize MipiDsiHandle.
g_mipiDsihandle[cntlr->devNo].priv = NULL;
cntlr->device = device; // Prerequisites for conversion between HdfDeviceObject and MipiDsiHandle.
device->service = &(cntlr->service); // Prerequisites for conversion between HdfDeviceObject and MipiDsiHandle.
cntlr->priv = NULL;
...
return HDF_SUCCESS;
}
...
return HDF_FAILURE;
}
```
```
static int32_t Hi35xxMipiTxInit(struct HdfDeviceObject *device)
{
int32_t ret;
g_mipiTx.priv = NULL; // g_mipiTx is a global variable defined.
// static struct MipiDsiCntlr g_mipiTx {
// .devNo=0
//};
g_mipiTx.ops = &g_method;// Attach the MipiDsiCntlrMethod instance.
ret = MipiDsiRegisterCntlr(&g_mipiTx, device);// (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
...
return MipiTxDrvInit(0); // (Mandatory) Device initialization customized by the vendor.
}
// mipi_dsi_core.c file
int32_t MipiDsiRegisterCntlr(struct MipiDsiCntlr *cntlr, struct HdfDeviceObject *device)
{
...
// Define the global variable static struct MipiDsiHandle g_mipiDsihandle[MAX_CNTLR_CNT].
if (g_mipiDsihandle[cntlr->devNo].cntlr == NULL) {
(void)OsalMutexInit(&g_mipiDsihandle[cntlr->devNo].lock);
(void)OsalMutexInit(&(cntlr->lock));
g_mipiDsihandle[cntlr->devNo].cntlr = cntlr;// Initialize MipiDsiHandle.
g_mipiDsihandle[cntlr->devNo].priv = NULL;
cntlr->device = device; // Prerequisites for conversion between HdfDeviceObject and MipiDsiHandle.
device->service = &(cntlr->service); // Prerequisites for conversion between HdfDeviceObject and MipiDsiHandle.
cntlr->priv = NULL;
...
return HDF_SUCCESS;
}
...
return HDF_FAILURE;
}
```
- **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** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
Releases the memory and deletes the controller. This function assigns values to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
>
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
```
static void Hi35xxMipiTxRelease(struct HdfDeviceObject *device)
{
struct MipiDsiCntlr *cntlr = NULL;
...
cntlr = MipiDsiCntlrFromDevice(device);// A forced conversion from HdfDeviceObject to MipiDsiCntlr is involved.
// return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service;
...
MipiTxDrvExit(; // (Mandatory) Release the resources occupied by the vendor's devices.
MipiDsiUnregisterCntlr(&g_mipiTx); // Empty function
g_mipiTx.priv = NULL;
HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__);
}
```
{
struct MipiDsiCntlr *cntlr = NULL;
...
cntlr = MipiDsiCntlrFromDevice(device);// A forced conversion from HdfDeviceObject to MipiDsiCntlr is involved.
// return (device == NULL) ? NULL : (struct MipiDsiCntlr *)device->service;
...
MipiTxDrvExit(; // (Mandatory) Release the resources occupied by the vendor's devices.
MipiDsiUnregisterCntlr(&g_mipiTx); // Empty function
g_mipiTx.priv = NULL;
HDF_LOGI("%s: unload mipi_tx driver 1212!", __func__);
}
```
......@@ -14,7 +14,7 @@ In the Hardware Driver Foundation (HDF), the MultiMedia Card (MMC) uses the inde
**MmcCntlrOps**:
```
struct MmcCntlrOps {
int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
......@@ -37,23 +37,23 @@ struct MmcCntlrOps {
**Table 1** Description of callback functions in MmcCntlrOps
| Function| Input Parameter| Return Value| Description|
| Function| Input Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- |
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| 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.|
| rescanSdioDev | **cntlr**: structure pointer to the MMC controller at the core layer.| HDF_STATUS| Scans and adds an SDIO device.|
## How to Develop
......@@ -75,6 +75,7 @@ The MMC module adaptation involves the following steps:
> For details about the functions in **MmcCntlrOps**, see [Available APIs](#available-apis).
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.
......@@ -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.
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.
MMC driver entry example:
```
struct HdfDriverEntry g_mmcDriverEntry = {
.moduleVersion = 1,
......@@ -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.
```
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.
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.
- **device_info.hcs** configuration example
```
root {
device_info {
......@@ -118,7 +123,7 @@ The following uses **himci.c** as an example to present the information required
policy = 2;
priority = 10;
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.
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
- **mmc_config.hcs** configuration example
```
root {
platform {
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 = "";
voltDef = 0; // 3.3V
freqMin = 50000; // (Mandatory) Minimum frequency
......@@ -165,7 +170,7 @@ The following uses **himci.c** as an example to present the information required
hostId = 0; // (Mandatory) Host ID
regBasePhy = 0x10020000;// (Mandatory) Physical base address of the register
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.
}
controller_0x10100000 :: mmc_controller {
......@@ -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).
- 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.
```
struct HimciHost {
struct MmcCntlr *mmc;// (Mandatory) Core layer structure
......@@ -225,7 +231,7 @@ The following uses **himci.c** as an example to present the information required
bool waitForEvent;
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 IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
......@@ -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**)
```
static struct MmcCntlrOps g_himciHostOps = {
.request = HimciDoRequest,
......@@ -284,22 +290,22 @@ The following uses **himci.c** as an example to present the information required
**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.
| Status| Description|
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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.|
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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 **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.
```
static int32_t HimciMmcBind(struct HdfDeviceObject *obj)
{
......@@ -309,18 +315,18 @@ The following uses **himci.c** as an example to present the information required
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));
host->mmc = cntlr; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
cntlr->priv = (void *)host; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
cntlr->ops = &g_himciHostOps; // (Mandatory) Attach the MmcCntlrOps instance.
cntlr->hdfDevObj = obj; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
ret = MmcCntlrParse(cntlr, obj); // (Mandatory) Initialize MmcCntlr. If the initialization fails, execute goto _ERR.
host->mmc = cntlr; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
cntlr->priv = (void *)host; // (Mandatory) Prerequisites for conversion between HimciHost and MmcCntlr.
cntlr->ops = &g_himciHostOps; // (Mandatory) Attach the MmcCntlrOps instance.
cntlr->hdfDevObj = obj; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
ret = MmcCntlrParse(cntlr, obj); // (Mandatory) Initialize MmcCntlr. If the initialization fails, execute goto _ERR.
...
ret = HimciHostParse(host, obj); // (Mandatory) Initialize HimciHost. If the initialization fails, execute goto _ERR.
ret = HimciHostParse(host, obj); // (Mandatory) Initialize HimciHost. If the initialization fails, execute goto _ERR.
...
ret = HimciHostInit(host, cntlr);// Customized initialization. If the initialization fails, execute goto _ERR.
ret = HimciHostInit(host, cntlr); // Customized initialization. If the initialization fails, execute goto _ERR.
...
ret = MmcCntlrAdd(cntlr); // Call the functions at the core layer. If the operation fails, execute goto _ERR.
ret = MmcCntlrAdd(cntlr); // Call the functions at the core layer. If the operation fails, execute goto _ERR.
...
(void)MmcCntlrAddDetectMsgToQueue(cntlr);// Add the card detection message to the queue.
HDF_LOGD("HimciMmcBind: success.");
......@@ -346,7 +352,7 @@ The following uses **himci.c** as an example to present the information required
Implements **ProcMciInit**.
```
static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
{
......@@ -374,16 +380,19 @@ The following uses **himci.c** as an example to present the information required
**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.
```
static void HimciMmcRelease(struct HdfDeviceObject *obj)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations.
static void HimciMmcRelease(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
...
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.
}
```
......@@ -20,10 +20,9 @@ Pin, as a software concept, provides APIs for uniformly managing the pins from d
### 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:
- 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.
- 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
### Available APIs
The **PinCntlrMethod** APIs are used to call the functions of the pin driver.
**PinCntlrMethod** definition:
The **PinCntlrMethod** structure defines callbacks to be invoked to call the functions of the pin driver.
```c
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
| API | Input Parameter | Output Parameter | Return Value| Description|
| ------------ | ------------------------------------------- | ------ | ---- | ---- |
......@@ -73,18 +71,22 @@ struct PinCntlrMethod {
The pin module adaptation procedure is as follows:
- Instantiate the driver entry.
- Configure attribute files.
- Instantiate the core layer APIs.
- Debug the driver.
1. Instantiate the driver entry.
2. Configure attribute files.
3. Instantiate the core layer APIs.
4. Debug the driver.
### Development Example
1. Instantiate the driver entry.
- 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**.
- 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.
```c
static struct HdfDriverEntry g_hi35xxPinDriverEntry = {
......@@ -92,13 +94,15 @@ The pin module adaptation procedure is as follows:
.Bind = Hi35xxPinBind,
.Init = Hi35xxPinInit,
.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.
- Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
```c
root {
device_info {
......@@ -106,8 +110,8 @@ The pin module adaptation procedure is as follows:
hostName = "platform_host";
priority = 50;
device_pin :: device {
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.
device0:: deviceNode { // Set an HDF device node for each pin controller.
policy = 0; // Policy for publishing services.
priority = 10; // Driver startup priority.
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. */
......@@ -122,13 +126,14 @@ The pin module adaptation procedure is as follows:
moduleName = "hi35xx_pin_driver";
deviceMatchAttr = "hisilicon_hi35xx_pin_1";
}
......
...
}
}
}
}
```
- 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:
```c
root {
......@@ -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.
number = 0; // (Mandatory) Controller ID.
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.
match_attr = "";
template pin_desc {
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.
F1 = ""; // Function 1.
F2 = ""; // Function 2.
......@@ -164,16 +169,18 @@ The pin module adaptation procedure is as follows:
F1 = "SFC_CLK";
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.
- Initialize the **PinCntlr** object.
Call **Hi35xxPinCntlrInit** to initialize the **PinCntlr** members.
```c
......@@ -209,14 +216,14 @@ The pin module adaptation procedure is as follows:
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 IDeviceIoService service;
struct HdfDeviceObject *device;
struct PinCntlrMethod *method;
struct DListHead node; // Node in the linked list.
struct DListHead node; // Node in the linked list.
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.
struct PinDesc *pins;
void *priv; // Private data.
......@@ -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
// 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 = {
.SetPinPull = Hi35xxPinSetPull, // Set the pull type.
.GetPinPull = Hi35xxPinGetPull, // Obtains the pull type.
.GetPinPull = Hi35xxPinGetPull, // Obtain the pull type.
.SetPinStrength = Hi35xxPinSetStrength, // Set the pull strength.
.GetPinStrength = Hi35xxPinGetStrength, // Obtains the pull strength.
.GetPinStrength = Hi35xxPinGetStrength, // Obtain the pull strength.
.SetPinFunc = Hi35xxPinSetFunc, // Set 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.
Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
**Return value**:
**HDF\_STATUS** <br>The table below describes some status. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.
| **State** | **Description** |
| **Status** | **Description** |
| ---------------------- | -------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
......@@ -299,8 +308,9 @@ The pin module adaptation procedure is as follows:
| HDF_SUCCESS | Initialization successful. |
| HDF_FAILURE | Initialization failed. |
Function description:
Initializes the custom structure object and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd()** function.
**Function description**:
Initializes the custom structure object and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd** function.
```c
static int32_t Hi35xxPinReadFunc(struct Hi35xxPinDesc *desc, const struct DeviceResourceNode *node, struct DeviceResourceIface *drsOps)
......@@ -322,7 +332,7 @@ The pin module adaptation procedure is as follows:
}
funcNum++;
......
...
return HDF_SUCCESS;
}
......@@ -341,7 +351,7 @@ The pin module adaptation procedure is as follows:
HDF_LOGE("%s: read pinName failed", __func__);
return ret;
}
......
...
ret = Hi35xxPinReadFunc(&hi35xx->desc[index], node, drsOps);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s:Pin read Func failed", __func__);
......@@ -349,20 +359,20 @@ The pin module adaptation procedure is as follows:
}
hi35xx->cntlr.pins[index].pinName = hi35xx->desc[index].pinName;
hi35xx->cntlr.pins[index].priv = (void *)node;
......
...
return HDF_SUCCESS;
}
static int32_t Hi35xxPinInit(struct HdfDeviceObject *device)
{
......
...
struct Hi35xxPinCntlr *hi35xx = NULL;
......
...
ret = Hi35xxPinCntlrInit(device, hi35xx); // Initialize the pin controller.
......
...
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { // Traverses each child node of the pin controller.
ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); // Parsing the child nodes.
......
ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); // Parse child nodes.
...
}
hi35xx->cntlr.method = &g_method; // Instantiate method.
......@@ -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.
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.
```c
static void Hi35xxPinRelease(struct HdfDeviceObject *device)
......@@ -426,4 +436,5 @@ The pin module adaptation procedure is as follows:
}
```
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.
......@@ -14,7 +14,7 @@ In the Hardware Driver Foundation (HDF), the Pulse Width Modulator (PWM) uses th
**PwmMethod**:
```
struct PwmMethod {
int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config);
......@@ -25,11 +25,11 @@ struct PwmMethod {
**Table 1** Description of callback functions in PwmMethod
| Function| Input Parameter| Return Value| Description|
| Function| Input Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- |
| 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.|
| close | **pwm**: structure pointer to the PWM controller at the core layer.| HDF_STATUS| Closes a device.|
| 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.|
| close | **pwm**: structure pointer to the PWM controller at the core layer.| HDF_STATUS| Closes a device.|
## How to Develop
......@@ -51,6 +51,7 @@ The PWM module adaptation involves the following steps:
> For details about the functions in **PwmMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
(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:
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.
PWM driver entry example:
PWM driver entry example:
```
struct HdfDriverEntry g_hdfPwm = {
.moduleVersion = 1,
......@@ -76,23 +81,26 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
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
```
root {
device_info {
platform :: host {
hostName = "platform_host";
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 {
policy = 1; // Publish kernel-mode services.
priority = 80; // Driver startup priority
permission = 0644; // Permission to create device nodes for the driver.
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.
policy = 1; // Publish services for kernel-mode processes.
priority = 80; // Driver startup priority.
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.
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.
// 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
```
- **pwm_config.hcs** configuration example
```
root {
platform {
......@@ -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
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.
```
struct HiPwm {
struct PwmDev dev; // (Mandatory) Core layer structure
......@@ -154,14 +163,14 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
struct IDeviceIoService service;
struct HdfDeviceObject *device;
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;
uint32_t num; // Device number
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 {
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 number; // Number of square waves to generate.
uint8_t polarity; // Polarity
......@@ -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**)
```
// The following uses pwm_hi35xx.c as an example. Fill the hook function.
struct PwmMethod g_pwmOps = {
......@@ -193,24 +202,24 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
**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.
| Status| Description|
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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.|
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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 object and **PwmDev**, and calls the **PwmDeviceAdd** function at the core layer.
```
// The bind function is empty. It can be combined with the init function or implement related operations based on the vendor's requirements.
// The Bind function is empty. It can be combined with the Init function or implement related operations based on service requirements.
static int32_t HdfPwmBind(struct HdfDeviceObject *obj)
{
(void)obj;
......@@ -237,16 +246,16 @@ The following uses **pwm_hi35xx.c** as an example to present the information req
iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);// Initialize the custom structure HiPwm.
...
hp->reg = (struct HiPwmRegs *)hp->base; // Initialize the custom structure HiPwm.
hp->supportPolarity = false; // Initialize the custom structure HiPwm.
hp->dev.method = &g_pwmOps; // Attach the PwmMethod instance.
hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE; // Initialize PwmDev.
hp->dev.cfg.period = PWM_DEFAULT_PERIOD; // Initialize PwmDev.
hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY; // Initialize PwmDev.
hp->dev.cfg.status = PWM_DISABLE_STATUS; // Initialize PwmDev.
hp->dev.cfg.number = 0; // Initialize PwmDev.
hp->dev.busy = false; // Initialize PwmDev.
if (PwmDeviceAdd(obj, &(hp->dev)) ) != HDF_SUCCESS) {// (Important) Call the core layer function to initialize hp->dev devices and services.
hp->reg = (struct HiPwmRegs *)hp->base; // Initialize the custom structure HiPwm.
hp->supportPolarity = false; // Initialize the custom structure HiPwm.
hp->dev.method = &g_pwmOps; // Attach the PwmMethod instance.
hp->dev.cfg.duty = PWM_DEFAULT_DUTY_CYCLE; // Initialize PwmDev.
hp->dev.cfg.period = PWM_DEFAULT_PERIOD; // Initialize PwmDev.
hp->dev.cfg.polarity = PWM_DEFAULT_POLARITY; // Initialize PwmDev.
hp->dev.cfg.status = PWM_DISABLE_STATUS; // Initialize PwmDev.
hp->dev.cfg.number = 0; // Initialize PwmDev.
hp->dev.busy = false; // Initialize PwmDev.
if (PwmDeviceAdd(obj, &(hp->dev)) ) != HDF_SUCCESS) { // Call the core layer function to initialize devices and services.
OsalIoUnmap((void *)hp->base);
return HDF_FAILURE;
}
......@@ -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.
```
static void HdfPwmRelease(struct HdfDeviceObject *obj)
{
......
......@@ -16,7 +16,7 @@ The regulator module is divided into the following layers:
- Core layer: provides the capabilities of binding, initializing, and releasing devices.
- 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
......@@ -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.
## Development Guidelines
### When to Use
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:
......@@ -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. |
| 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:
......@@ -86,9 +86,11 @@ The regulator module adaptation procedure is as follows:
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 = {
......@@ -116,7 +118,7 @@ The regulator module adaptation procedure is as follows:
| permission | Driver permission. |
| moduleName | **HDF_PLATFORM_REGULATOR_MANAGER** |
| serviceName | **HDF_PLATFORM_REGULATOR_MANAGER** |
| deviceMatchAttr | This parameter is reserved. |
| deviceMatchAttr | Reserved. |
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:
device_regulator :: device {
device0:: deviceNode { // Set an HDF device node for each regulator controller.
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.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
......@@ -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).
......@@ -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**.
```
// RegulatorNode is the core layer controller structure. The Init function assigns values to the members of RegulatorNode.
struct RegulatorNode {
......@@ -219,17 +219,17 @@ The regulator module adaptation procedure is as follows:
};
struct RegulatorDesc {
const char *name; /* Regulator name. */
const char *parentName; /* Regulator parent node name. */
const char *name; /* Regulator name. */
const char *parentName; /* Regulator parent node name. */
struct RegulatorConstraints constraints; /* Regulator constraint information. */
uint32_t minUv; /* Minimum output voltage. */
uint32_t maxUv; /* Maximum output voltage. */
uint32_t minUa; /* Minimum output current. */
uint32_t maxUa; /* Maximum output current. */
uint32_t status; /* Regulator status, which can be on or off. */
uint32_t minUv; /* Minimum output voltage. */
uint32_t maxUv; /* Maximum output voltage. */
uint32_t minUa; /* Minimum output current. */
uint32_t maxUa; /* Maximum output current. */
uint32_t status; /* Regulator status, which can be on or off. */
int useCount;
int consumerRegNums; /* Number of regulator consumers. */
RegulatorStatusChangecb cb; /* Variable used to notify the regulator status changes. */
int consumerRegNums; /* Number of the regulator consumers. */
RegulatorStatusChangecb cb; /* Variable used to notify the regulator status changes. */
};
struct RegulatorConstraints {
......@@ -259,81 +259,81 @@ The regulator module adaptation procedure is as follows:
};
```
- **Init** function
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**HDF\_STATUS**
The table below lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.
**Table 2** HDF_STATUS
| State | Description |
| ---------------------- | -------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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.
```c
static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device)
{
int32_t ret;
const struct DeviceResourceNode *childNode = NULL;
...
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
ret = VirtualRegulatorParseAndInit(device, childNode);// (Mandatory) The implementation is as follows:
...
}
...
}
static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
int32_t ret;
struct RegulatorNode *regNode = NULL;
(void)device;
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.
...
}
```
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**HDF\_STATUS**
The table below describes some status. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.
**Table 2** Description of HDF_STATUS
| Status | Description |
| ---------------------- | -------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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.
```c
static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device)
{
int32_t ret;
const struct DeviceResourceNode *childNode = NULL;
...
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
ret = VirtualRegulatorParseAndInit(device, childNode);// (Mandatory) The implementation is as follows:
...
}
...
}
static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
int32_t ret;
struct RegulatorNode *regNode = NULL;
(void)device;
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
Input parameter:
**Input parameter**:
**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.
```c
static void VirtualRegulatorRelease(struct HdfDeviceObject *device)
{
......@@ -341,7 +341,7 @@ The regulator module adaptation procedure is as follows:
RegulatorNodeRemoveAll();// (Mandatory) Call the function at the core layer to release regulator controller devices and services.
}
```
4. Debug the driver.
(Optional) Verify the basic functions of the new driver, for example, check whether the test cases are successful after the driver is loaded.
......
......@@ -14,7 +14,7 @@ The real-time clock (RTC) is a real-time clock device in the operating system. I
**RtcMethod**:
```
struct RtcMethod {
int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time);
......@@ -33,19 +33,19 @@ struct RtcMethod {
**Table 1** Description of the callback functions in RtcMethod
| Function| Input Parameter| Output Parameter| Return Value| Description|
| Function| Input Parameter| Output Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| ReadTime | **host**: structure pointer to the RTC controller at the core layer.| **time**: structure pointer to the time read.| HDF_STATUS| Reads the RTC time.|
| WriteTime | **host**: structure pointer to the RTC controller at the core layer.<br>**time**: structure pointer to the time to write.| –| HDF_STATUS| Writes the RTC time (including the year, month, day, day of week, hour, minute, second, and millisecond).|
| ReadAlarm | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.| **time**: structure pointer to the time read.| HDF_STATUS| Reads the RTC alarm time.|
| WriteAlarm | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**time**: structure pointer to the time to write.| –| HDF_STATUS| Writes the RTC alarm time.|
| RegisterAlarmCallback | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**cb**: pointer to the callback to register.| –| HDF_STATUS| Registers a callback to be invoked when an alarm is not generated at the specified time.|
| AlarmInterruptEnable | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**enable**: whether to enable interrupts for an RTC alarm. | –| HDF_STATUS| Enables or disables interrupts for an RTC alarm.|
| GetFreq | **host**: structure pointer to the RTC controller at the core layer.| **freq**: pointer to the frequency obtained, which is of the uint32_t type.| HDF_STATUS| Obtains the frequency of the external crystal oscillator connected to the RTC driver.|
| SetFreq | **host**: structure pointer to the RTC controller at the core layer.<br>**freq**: frequency to set, which is of the uint32_t type.| –| HDF_STATUS| Sets the frequency of the external crystal oscillator connected to the RTC driver.|
| Reset | **host**: structure pointer to the RTC controller at the core layer.| –| HDF_STATUS| Resets the RTC.|
| ReadReg | **host**: structure pointer to the RTC controller at the core layer.<br>**usrDefIndex**: index of a custom register.| **value**: pointer to the register value obtained, which is of the uint8_t type.| HDF_STATUS| Reads a custom RTC register. A register index corresponds to one byte of the register value.|
| WriteReg | **host**: structure pointer to the RTC controller at the core layer.<br>**usrDefIndex**: index of a custom register.<br>**value**: register value to write, which is of the uint8_t type.| –| HDF_STATUS| Writes a custom RTC register. A register index corresponds to one byte of the register value.|
| ReadTime | **host**: structure pointer to the RTC controller at the core layer.| **time**: structure pointer to the time read.| HDF_STATUS| Reads the RTC time.|
| WriteTime | **host**: structure pointer to the RTC controller at the core layer.<br>**time**: structure pointer to the time to write.| –| HDF_STATUS| Writes the RTC time (including the year, month, day, day of week, hour, minute, second, and millisecond).|
| ReadAlarm | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.| **time**: structure pointer to the time read.| HDF_STATUS| Reads the RTC alarm time.|
| WriteAlarm | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**time**: structure pointer to the time to write.| –| HDF_STATUS| Writes the RTC alarm time.|
| RegisterAlarmCallback | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**cb**: pointer to the callback to register.| –| HDF_STATUS| Registers a callback to be invoked when an alarm is not generated at the specified time.|
| AlarmInterruptEnable | **host**: structure pointer to the RTC controller at the core layer.<br>**alarmIndex**: RTC alarm index, which is an enumerated value.<br>**enable**: whether to enable interrupts for an RTC alarm. | –| HDF_STATUS| Enables or disables interrupts for an RTC alarm.|
| GetFreq | **host**: structure pointer to the RTC controller at the core layer.| **freq**: pointer to the frequency obtained, which is of the uint32_t type.| HDF_STATUS| Obtains the frequency of the external crystal oscillator connected to the RTC driver.|
| SetFreq | **host**: structure pointer to the RTC controller at the core layer.<br>**freq**: frequency to set, which is of the uint32_t type.| –| HDF_STATUS| Sets the frequency of the external crystal oscillator connected to the RTC driver.|
| Reset | **host**: structure pointer to the RTC controller at the core layer.| –| HDF_STATUS| Resets the RTC.|
| ReadReg | **host**: structure pointer to the RTC controller at the core layer.<br>**usrDefIndex**: index of a custom register.| **value**: pointer to the register value obtained, which is of the uint8_t type.| HDF_STATUS| Reads a custom RTC register. A register index corresponds to one byte of the register value.|
| WriteReg | **host**: structure pointer to the RTC controller at the core layer.<br>**usrDefIndex**: index of a custom register.<br>**value**: register value to write, which is of the uint8_t type.| –| HDF_STATUS| Writes a custom RTC register. A register index corresponds to one byte of the register value.|
## How to Develop
......@@ -67,6 +67,7 @@ The RTC module adaptation involves the following steps:
> For details about the functions in **RtcMethod**, see [Available APIs](#available-apis).
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, such as the RTC status control and response to interrupts.
......@@ -74,31 +75,37 @@ The RTC module adaptation involves the following steps:
The following uses **rtc_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.
RTC driver entry example:
RTC driver entry example:
```
struct HdfDriverEntry g_rtcDriverEntry = {
.moduleVersion = 1,
.Bind = HiRtcBind, // See the Bind function.
.Init = HiRtcInit, // See the Init function.
.Release = HiRtcRelease, //See the Release function.
.Init = HiRtcInit, // See the Init function.
.Release = HiRtcRelease, //See the Release function.
.moduleName = "HDF_PLATFORM_RTC", // (Mandatory) The value must be the same as that in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_rtcDriverEntry);
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **rtc_config.hcs** file.
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **rtc_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 **RtcHost** members at the core layer.
In this example, there is only one RTC controller. If there are multiple RTC controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **rtc_config** file for each controller.
- **device_info.hcs** configuration example
```
root {
device_info {
......@@ -107,9 +114,9 @@ The following uses **rtc_hi35xx.c** as an example to present the information req
device0 :: deviceNode {
policy = 1; // The driver publishes services for kernel-mode processes only.
priority = 30; // A smaller value indicates a higher priority.
permission = 0644; // Permission for the driver to create a device node
permission = 0644; // Permission for the driver to create a device node
moduleName = "HDF_PLATFORM_RTC"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_PLATFORM_RTC"; // (Mandatory) Unique name of the service published by the driver.
serviceName = "HDF_PLATFORM_RTC"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hisilicon_hi35xx_rtc";// The value must be the same as that of match_attr in the .hcs file.
}
}
......@@ -120,7 +127,7 @@ The following uses **rtc_hi35xx.c** as an example to present the information req
- **rtc_config.hcs** configuration example
```
root {
platform {
......@@ -143,25 +150,25 @@ The following uses **rtc_hi35xx.c** as an example to present the information req
}
```
3. Initialize the **RtcHost** 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 **RtcMethod** in **RtcHost** (so that the underlying driver functions can be called).
3. Initialize the **RtcHost** 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 **RtcMethod** in **RtcHost** (so that the underlying driver functions can be called).
- 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 **rtc_config.hcs** file to initialize the members in the custom structure.
```
struct RtcConfigInfo {
uint32_t spiBaseAddr; // Used for address mapping.
uint32_t spiBaseAddr; // Used for address mapping.
volatile void *remapBaseAddr; // Used for address mapping.
uint16_t regAddrLength; // Used for address mapping.
uint8_t supportAnaCtrl; // Whether ANACTRL is supported.
uint8_t supportLock; // Whether lock is supported.
uint8_t irq; // Interrupt number.
uint8_t alarmIndex; // RTC alarm index.
uint8_t anaCtrlAddr; // ANACTRL address.
struct RtcLockAddr lockAddr; // Lock address.
RtcAlarmCallback cb; // Callback.
struct OsalMutex mutex; // Mutex.
uint16_t regAddrLength; // Used for address mapping.
uint8_t supportAnaCtrl; // Whether ANACTRL is supported.
uint8_t supportLock; // Whether lock is supported.
uint8_t irq; // Interrupt number.
uint8_t alarmIndex; // RTC alarm index.
uint8_t anaCtrlAddr; // ANACTRL address.
struct RtcLockAddr lockAddr; // Lock address.
RtcAlarmCallback cb; // Callback.
struct OsalMutex mutex; // Mutex.
};
// RtcHost is the controller structure at the core layer. The Init function assigns values to the members of RtcHost.
......@@ -172,125 +179,130 @@ The following uses **rtc_hi35xx.c** as an example to present the information req
void *data;
};
```
- Instantiating **RtcMethod** in **RtcHost** (other members are initialized by **Init**)
```
// Example in rtc_hi35xx.c: instantiate the hook.
static struct RtcMethod g_method = {
.ReadTime = HiRtcReadTime,
.WriteTime = HiRtcWriteTime,
.ReadAlarm = HiReadAlarm,
.WriteAlarm = HiWriteAlarm,
.RegisterAlarmCallback = HiRegisterAlarmCallback,
.AlarmInterruptEnable = HiAlarmInterruptEnable,
.GetFreq = HiGetFreq,
.SetFreq = HiSetFreq,
.Reset = HiReset,
.ReadReg = HiReadReg,
.WriteReg = HiWriteReg,
};
// Example in rtc_hi35xx.c: instantiate the hook.
static struct RtcMethod g_method = {
.ReadTime = HiRtcReadTime,
.WriteTime = HiRtcWriteTime,
.ReadAlarm = HiReadAlarm,
.WriteAlarm = HiWriteAlarm,
.RegisterAlarmCallback = HiRegisterAlarmCallback,
.AlarmInterruptEnable = HiAlarmInterruptEnable,
.GetFreq = HiGetFreq,
.SetFreq = HiSetFreq,
.Reset = HiReset,
.ReadReg = HiReadReg,
.WriteReg = HiWriteReg,
};
```
- **Bind** function
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
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.
**Table 2** HDF_STATUS
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**HDF_STATUS**
The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
**Table 2** Description of HDF_STATUS
| Status | Description |
| ---------------------- | -------------------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object. |
| 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**:
Binds the **HdfDeviceObject** object and **RtcHost**.
```
static int32_t HiRtcBind(struct HdfDeviceObject *device)
{
struct RtcHost *host = NULL;
host = RtcHostCreate(device); // Allocate memory and attach the device host and the device.
// Prerequisite for conversion between HdfDeviceObject and RtcHost.
...
device->service = &host->service; // Prerequisite for conversion between HdfDeviceObject and RtcHost.
// It helps implement the global host by calling RtcHostFromDevice.
return HDF_SUCCESS;
}
```
- **Init** function
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
HDF_STATUS
Function description:
Initializes the custom structure object and **RtcHost**.
```
static int32_t HiRtcInit(struct HdfDeviceObject *device)
{
struct RtcHost *host = NULL;
struct RtcConfigInfo *rtcInfo = NULL;
...
host = RtcHostFromDevice(device);// Forcibly convert HdfDeviceObject to RtcHost.
rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
...
// HiRtcConfigData reads attributes from the device configuration tree and fills the values in supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength, and irq in rtcInfo.
// Provide parameters for HiRtcSwInit and HiRtcSwInit. When HiRtcSwInit and HiRtcSwInit fail to be executed internally, Release() can be called to release memory.
if (HiRtcConfigData(rtcInfo, device->property) != 0) {
...
}
if (HiRtcSwInit(rtcInfo)! = 0) {// Address mapping and interrupt registration.
...
}
if (HiRtcHwInit(rtcInfo)! = 0) {// Initialize ANACTRL and lockAddr.
```
static int32_t HiRtcBind(struct HdfDeviceObject *device)
{
struct RtcHost *host = NULL;
host = RtcHostCreate(device); // Allocate memory and attach the device host with the device.
// Prerequisite for conversion between HdfDeviceObject and RtcHost.
...
device->service = &host->service; // Prerequisite for conversion between HdfDeviceObject and RtcHost.
// It helps implement a global host by calling RtcHostFromDevice.
return HDF_SUCCESS;
}
host->method = &g_method; // Attach the RtcMethod instance.
host->data = rtcInfo; // Prerequisites for conversion between RtcConfigInfo and RtcHost.
HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
return HDF_SUCCESS;
}
```
```
- **Init** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**HDF_STATUS**
**Function description**:
Initializes the custom structure object and **RtcHost**.
```
static int32_t HiRtcInit(struct HdfDeviceObject *device)
{
struct RtcHost *host = NULL;
struct RtcConfigInfo *rtcInfo = NULL;
...
host = RtcHostFromDevice(device);// Forcibly convert HdfDeviceObject to RtcHost.
rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
...
// HiRtcConfigData reads attributes from the device configuration tree and fills in supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength and irq of RTCInfo.
// Provide parameters for HiRtcSwInit and HiRtcSwInit. When HiRtcSwInit and HiRtcSwInit fail to be executed internally, Release() can be called to release memory.
if (HiRtcConfigData(rtcInfo, device->property) != 0) {
...
}
if (HiRtcSwInit(rtcInfo)! = 0) {// Address mapping and interrupt registration.
...
}
if (HiRtcHwInit(rtcInfo)! = 0) {// Initialize ANACTRL and lockAddr.
...
}
host->method = &g_method; // Attach the RtcMethod instance.
host->data = rtcInfo; // Prerequisites for conversion between RtcConfigInfo and RtcHost.
HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
return HDF_SUCCESS;
}
```
- **Release** function
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
No value is returned.
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** or **Bind** function has the corresponding value assignment operations.
```
static void HiRtcRelease(struct HdfDeviceObject *device)
{
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
No value is returned.
**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.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** or **Bind** function has the corresponding value assignment operations.
```
static void HiRtcRelease(struct HdfDeviceObject *device)
{
struct RtcHost *host = NULL;
struct RtcConfigInfo *rtcInfo = NULL;
...
......@@ -302,5 +314,5 @@ The following uses **rtc_hi35xx.c** as an example to present the information req
host->data = NULL;
}
RtcHostDestroy(host); // Release RtcHost.
}
```
}
```
# SDIO<a name="EN-US_TOPIC_0000001199682295"></a>
# SDIO
## Overview<a name="section1347805272150053"></a>
## Overview
A Secure Digital Input Output \(SDIO\) card is an extension of the SD specification to cover I/O functions. SD and SDIO cards are called multimedia cards \(MMCs\). In the Hardware Driver Foundation \(HDF\) framework, the SDIO module uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to handle external access requests. After receiving an access request from an API, the device manager extracts the parameters in the request to call the internal method of the target device. In the independent service mode, the service management capabilities of the HDFDeviceManager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
A Secure Digital Input Output (SDIO) card is an extension of the SD specification to cover I/O functions. SD and SDIO cards are called multimedia cards (MMCs). In the Hardware Driver Foundation (HDF), the SDIO module uses the independent service mode for API adaptation. In this mode, each device independently publishes a service to process external access requests. When receiving an access request, the HDF DeviceManager extracts parameters from the request to call the internal APIs of the target device. In the independent service mode, the HDF DeviceManager provides service management capabilities. However, you need to configure a node for each device, which increases memory usage.
**Figure 1** Independent service mode<a name="fig124181331222"></a>
![](figures/independent-service-mode.png "independent-service-mode-12")
**Figure 1** Independent service mode
## Available APIs<a name="section752964871810"></a>
![image](figures/independent-service-mode.png)
## Available APIs
**SdioDeviceOps**:
SdioDeviceOps
```
// Function template
......@@ -35,522 +38,293 @@ struct SdioDeviceOps {
};
```
**Table 1** Callbacks for the members in the SdioDeviceOps structure
<a name="table878215448417"></a>
<table><thead align="left"><tr id="row17784344241"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p67842444414"><a name="p67842444414"></a><a name="p67842444414"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p1978411444416"><a name="p1978411444416"></a><a name="p1978411444416"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p87841441243"><a name="p87841441243"></a><a name="p87841441243"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p12784174417415"><a name="p12784174417415"></a><a name="p12784174417415"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p16784104418413"><a name="p16784104418413"></a><a name="p16784104418413"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row8784144449"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1378415443418"><a name="p1378415443418"></a><a name="p1378415443418"></a>incrAddrReadBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p13126132382019"><a name="p13126132382019"></a><a name="p13126132382019"></a><strong id="b5125152392019"><a name="b5125152392019"></a><a name="b5125152392019"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p539123116208"><a name="p539123116208"></a><a name="p539123116208"></a><strong id="b239531132010"><a name="b239531132010"></a><a name="b239531132010"></a>addr</strong>: SDIO address, which is of the uint32_t type.</p>
<p id="p177857442043"><a name="p177857442043"></a><a name="p177857442043"></a><strong id="b10613113712815"><a name="b10613113712815"></a><a name="b10613113712815"></a>size</strong>: size of the data to read, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p207851447410"><a name="p207851447410"></a><a name="p207851447410"></a><strong id="b77141033182915"><a name="b77141033182915"></a><a name="b77141033182915"></a>data</strong>: pointer to the output value, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p167851644547"><a name="p167851644547"></a><a name="p167851644547"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p37855441645"><a name="p37855441645"></a><a name="p37855441645"></a>Incrementally reads data of a given length from the specified SDIO address.</p>
</td>
</tr>
<tr id="row197851446413"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p5785174419412"><a name="p5785174419412"></a><a name="p5785174419412"></a>incrAddrWriteBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p13541153612013"><a name="p13541153612013"></a><a name="p13541153612013"></a><strong id="b6541103617209"><a name="b6541103617209"></a><a name="b6541103617209"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p1455963952010"><a name="p1455963952010"></a><a name="p1455963952010"></a><strong id="b165592039142016"><a name="b165592039142016"></a><a name="b165592039142016"></a>data</strong>: pointer to the input value, which is of the uint8_t type.</p>
<p id="p7565542172010"><a name="p7565542172010"></a><a name="p7565542172010"></a><strong id="b0565342182016"><a name="b0565342182016"></a><a name="b0565342182016"></a>addr</strong>: SDIO address, which is of the uint32_t type.</p>
<p id="p078554411417"><a name="p078554411417"></a><a name="p078554411417"></a><strong id="b1773173211314"><a name="b1773173211314"></a><a name="b1773173211314"></a>size</strong>: size of the data to write, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678519441748"><a name="p678519441748"></a><a name="p678519441748"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p778594419416"><a name="p778594419416"></a><a name="p778594419416"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p67851444445"><a name="p67851444445"></a><a name="p67851444445"></a>Incrementally writes data of a given length to the specified SDIO address.</p>
</td>
</tr>
<tr id="row11785154419412"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p978514412418"><a name="p978514412418"></a><a name="p978514412418"></a>fixedAddrReadBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p35454464204"><a name="p35454464204"></a><a name="p35454464204"></a><strong id="b3545746122016"><a name="b3545746122016"></a><a name="b3545746122016"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p98261449132010"><a name="p98261449132010"></a><a name="p98261449132010"></a><strong id="b182684922010"><a name="b182684922010"></a><a name="b182684922010"></a>addr</strong>: SDIO address, which is of the uint32_t type.</p>
<p id="p4926105372014"><a name="p4926105372014"></a><a name="p4926105372014"></a><strong id="b10926175314206"><a name="b10926175314206"></a><a name="b10926175314206"></a>size</strong>: size of the data to read, which is of the uint32_t type.</p>
<p id="p15786144419415"><a name="p15786144419415"></a><a name="p15786144419415"></a><strong id="b17163219183711"><a name="b17163219183711"></a><a name="b17163219183711"></a>scatterLen</strong>: data length, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p9786124418414"><a name="p9786124418414"></a><a name="p9786124418414"></a><strong id="b14137104917373"><a name="b14137104917373"></a><a name="b14137104917373"></a>data</strong>: pointer to the output value, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p2078614441842"><a name="p2078614441842"></a><a name="p2078614441842"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p107861744143"><a name="p107861744143"></a><a name="p107861744143"></a>Reads data of a given length from a fixed SDIO address.</p>
</td>
</tr>
<tr id="row278618441241"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p137861244448"><a name="p137861244448"></a><a name="p137861244448"></a>fixedAddrWriteBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1080445917207"><a name="p1080445917207"></a><a name="p1080445917207"></a><strong id="b380445918202"><a name="b380445918202"></a><a name="b380445918202"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p0833423219"><a name="p0833423219"></a><a name="p0833423219"></a><strong id="b1583316216211"><a name="b1583316216211"></a><a name="b1583316216211"></a>data</strong>: pointer to the input value, which is of the uint8_t type.</p>
<p id="p6700146102112"><a name="p6700146102112"></a><a name="p6700146102112"></a><strong id="b117001967218"><a name="b117001967218"></a><a name="b117001967218"></a>addr</strong>: SDIO address, which is of the uint32_t type.</p>
<p id="p1068901013214"><a name="p1068901013214"></a><a name="p1068901013214"></a><strong id="b368914103212"><a name="b368914103212"></a><a name="b368914103212"></a>size</strong>: size of the data to write, which is of the uint32_t type.</p>
<p id="p77861444341"><a name="p77861444341"></a><a name="p77861444341"></a><strong id="b1654516614113"><a name="b1654516614113"></a><a name="b1654516614113"></a>scatterLen</strong>: data length, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p5786244345"><a name="p5786244345"></a><a name="p5786244345"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p147868442416"><a name="p147868442416"></a><a name="p147868442416"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1478615441948"><a name="p1478615441948"></a><a name="p1478615441948"></a>Writes data of a given length to the fixed SDIO address.</p>
</td>
</tr>
<tr id="row1078694416418"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p12786154414413"><a name="p12786154414413"></a><a name="p12786154414413"></a>func0ReadBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p97041515162116"><a name="p97041515162116"></a><a name="p97041515162116"></a><strong id="b470412150211"><a name="b470412150211"></a><a name="b470412150211"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p1029871817216"><a name="p1029871817216"></a><a name="p1029871817216"></a><strong id="b17298191818216"><a name="b17298191818216"></a><a name="b17298191818216"></a>addr</strong>: SDIO address, which is of the uint32_t type.</p>
<p id="p4786244541"><a name="p4786244541"></a><a name="p4786244541"></a><strong id="b207721914423"><a name="b207721914423"></a><a name="b207721914423"></a>size</strong>: size of the data to read, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p37868445420"><a name="p37868445420"></a><a name="p37868445420"></a><strong id="b8335193874220"><a name="b8335193874220"></a><a name="b8335193874220"></a>data</strong>: pointer to the output value, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p197874442416"><a name="p197874442416"></a><a name="p197874442416"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p107877441146"><a name="p107877441146"></a><a name="p107877441146"></a>Reads data of a given length from the address space of SDIO function 0.</p>
</td>
</tr>
<tr id="row1478794415414"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p12787644548"><a name="p12787644548"></a><a name="p12787644548"></a>func0WriteBytes</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p11251122313211"><a name="p11251122313211"></a><a name="p11251122313211"></a><strong id="b625117238213"><a name="b625117238213"></a><a name="b625117238213"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p172811926172111"><a name="p172811926172111"></a><a name="p172811926172111"></a><strong id="b528102618213"><a name="b528102618213"></a><a name="b528102618213"></a>data</strong>: pointer to the input value, which is of the uint8_t type.</p>
<p id="p17651829162116"><a name="p17651829162116"></a><a name="p17651829162116"></a><strong id="b1465142962118"><a name="b1465142962118"></a><a name="b1465142962118"></a>addr</strong>: SDIO address, which is of the uint32_t type.</p>
<p id="p67871544242"><a name="p67871544242"></a><a name="p67871544242"></a><strong id="b394817346436"><a name="b394817346436"></a><a name="b394817346436"></a>size</strong>: size of the data to write, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678774413416"><a name="p678774413416"></a><a name="p678774413416"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p207871944648"><a name="p207871944648"></a><a name="p207871944648"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p57876441415"><a name="p57876441415"></a><a name="p57876441415"></a>Writes data of a given length to the address space of SDIO function 0.</p>
</td>
</tr>
<tr id="row157871441145"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1878714442417"><a name="p1878714442417"></a><a name="p1878714442417"></a>setBlockSize</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p16155033152118"><a name="p16155033152118"></a><a name="p16155033152118"></a><strong id="b71556330213"><a name="b71556330213"></a><a name="b71556330213"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p187872445410"><a name="p187872445410"></a><a name="p187872445410"></a><strong id="b12844183820441"><a name="b12844183820441"></a><a name="b12844183820441"></a>blockSize</strong>: block size, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p77878444415"><a name="p77878444415"></a><a name="p77878444415"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p37871244243"><a name="p37871244243"></a><a name="p37871244243"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p378710441647"><a name="p378710441647"></a><a name="p378710441647"></a>Sets the block size.</p>
</td>
</tr>
<tr id="row15787344349"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p878819441048"><a name="p878819441048"></a><a name="p878819441048"></a>getCommonInfo</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p114691537132117"><a name="p114691537132117"></a><a name="p114691537132117"></a><strong id="b6469143713211"><a name="b6469143713211"></a><a name="b6469143713211"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p1078820442419"><a name="p1078820442419"></a><a name="p1078820442419"></a><strong id="b12145522184712"><a name="b12145522184712"></a><a name="b12145522184712"></a>infoType</strong>: info type, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678814411418"><a name="p678814411418"></a><a name="p678814411418"></a><strong id="b83512634819"><a name="b83512634819"></a><a name="b83512634819"></a>info</strong>: structure pointer to the output <strong id="b59131139164813"><a name="b59131139164813"></a><a name="b59131139164813"></a>SdioFuncInfo</strong>.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1578894410419"><a name="p1578894410419"></a><a name="p1578894410419"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p7788444140"><a name="p7788444140"></a><a name="p7788444140"></a>Obtains <strong id="b176819272491"><a name="b176819272491"></a><a name="b176819272491"></a>CommonInfo</strong>. For details, see the <strong id="b1127411492595"><a name="b1127411492595"></a><a name="b1127411492595"></a>NOTE</strong> below this table.</p>
</td>
</tr>
<tr id="row7788154410416"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p6788104410419"><a name="p6788104410419"></a><a name="p6788104410419"></a>setCommonInfo</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p10540104472112"><a name="p10540104472112"></a><a name="p10540104472112"></a><strong id="b1954014420218"><a name="b1954014420218"></a><a name="b1954014420218"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p9107164817213"><a name="p9107164817213"></a><a name="p9107164817213"></a><strong id="b410734816213"><a name="b410734816213"></a><a name="b410734816213"></a>info</strong>: union pointer to the input <strong id="b610774812211"><a name="b610774812211"></a><a name="b610774812211"></a>SdioFuncInfo</strong>.</p>
<p id="p2078815442417"><a name="p2078815442417"></a><a name="p2078815442417"></a><strong id="b138611646185019"><a name="b138611646185019"></a><a name="b138611646185019"></a>infoType</strong>: info type, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p13788644043"><a name="p13788644043"></a><a name="p13788644043"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p19788134418420"><a name="p19788134418420"></a><a name="p19788134418420"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1278814415412"><a name="p1278814415412"></a><a name="p1278814415412"></a>Sets <strong id="b840010395517"><a name="b840010395517"></a><a name="b840010395517"></a>CommonInfo</strong>. For details, see the <strong id="b44901724012"><a name="b44901724012"></a><a name="b44901724012"></a>NOTE</strong> below this table.</p>
</td>
</tr>
<tr id="row1788344744"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p2078819441745"><a name="p2078819441745"></a><a name="p2078819441745"></a>flushData</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p67888441442"><a name="p67888441442"></a><a name="p67888441442"></a><strong id="b4882145105215"><a name="b4882145105215"></a><a name="b4882145105215"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1478812441147"><a name="p1478812441147"></a><a name="p1478812441147"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p3789174418420"><a name="p3789174418420"></a><a name="p3789174418420"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p578912441445"><a name="p578912441445"></a><a name="p578912441445"></a>Calls the function when the SDIO device needs to be re-initialized or an error occurs.</p>
</td>
</tr>
<tr id="row19789244142"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p778913441417"><a name="p778913441417"></a><a name="p778913441417"></a>enableFunc</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p12789144418412"><a name="p12789144418412"></a><a name="p12789144418412"></a><strong id="b1029151718538"><a name="b1029151718538"></a><a name="b1029151718538"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p678964419417"><a name="p678964419417"></a><a name="p678964419417"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p97891744946"><a name="p97891744946"></a><a name="p97891744946"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p127891445415"><a name="p127891445415"></a><a name="p127891445415"></a>Enables the SDIO device.</p>
</td>
</tr>
<tr id="row177898441647"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p978917447412"><a name="p978917447412"></a><a name="p978917447412"></a>disableFunc</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1978911449418"><a name="p1978911449418"></a><a name="p1978911449418"></a><strong id="b529982985311"><a name="b529982985311"></a><a name="b529982985311"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p57898448413"><a name="p57898448413"></a><a name="p57898448413"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p77893441341"><a name="p77893441341"></a><a name="p77893441341"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1479019449414"><a name="p1479019449414"></a><a name="p1479019449414"></a>Disables the SDIO device.</p>
</td>
</tr>
<tr id="row17908444415"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1279017441140"><a name="p1279017441140"></a><a name="p1279017441140"></a>claimIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1867751642210"><a name="p1867751642210"></a><a name="p1867751642210"></a><strong id="b12677816192216"><a name="b12677816192216"></a><a name="b12677816192216"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p1279018442419"><a name="p1279018442419"></a><a name="p1279018442419"></a><strong id="b471593695213"><a name="b471593695213"></a><a name="b471593695213"></a>irqHandler</strong>: void function pointer to the IRQ handler.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p379084411411"><a name="p379084411411"></a><a name="p379084411411"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1179074410416"><a name="p1179074410416"></a><a name="p1179074410416"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p6790124418410"><a name="p6790124418410"></a><a name="p6790124418410"></a>Claims an SDIO IRQ.</p>
</td>
</tr>
<tr id="row177909441647"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p77900441411"><a name="p77900441411"></a><a name="p77900441411"></a>releaseIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p27902441414"><a name="p27902441414"></a><a name="p27902441414"></a><strong id="b143101291537"><a name="b143101291537"></a><a name="b143101291537"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p87906441742"><a name="p87906441742"></a><a name="p87906441742"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p147906446419"><a name="p147906446419"></a><a name="p147906446419"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p77901544440"><a name="p77901544440"></a><a name="p77901544440"></a>Releases an SDIO IRQ.</p>
</td>
</tr>
<tr id="row97906449416"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p579024419411"><a name="p579024419411"></a><a name="p579024419411"></a>findFunc</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p181282417222"><a name="p181282417222"></a><a name="p181282417222"></a><strong id="b81210244229"><a name="b81210244229"></a><a name="b81210244229"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
<p id="p5791184417414"><a name="p5791184417414"></a><a name="p5791184417414"></a><strong id="b34537192557"><a name="b34537192557"></a><a name="b34537192557"></a>configData</strong>: structure pointer to the key SDIO function information.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1079112441345"><a name="p1079112441345"></a><a name="p1079112441345"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p17916446420"><a name="p17916446420"></a><a name="p17916446420"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p779119441549"><a name="p779119441549"></a><a name="p779119441549"></a>Obtains the matching funcNum.</p>
</td>
</tr>
<tr id="row779116446417"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p679119448412"><a name="p679119448412"></a><a name="p679119448412"></a>claimHost</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p179116441547"><a name="p179116441547"></a><a name="p179116441547"></a><strong id="b931692913535"><a name="b931692913535"></a><a name="b931692913535"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p97911144944"><a name="p97911144944"></a><a name="p97911144944"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p12791244341"><a name="p12791244341"></a><a name="p12791244341"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p5791134412417"><a name="p5791134412417"></a><a name="p5791134412417"></a>Claims a host exclusively.</p>
</td>
</tr>
<tr id="row47911344746"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p279113441046"><a name="p279113441046"></a><a name="p279113441046"></a>releaseHost</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p67916449413"><a name="p67916449413"></a><a name="p67916449413"></a><strong id="b1632011295536"><a name="b1632011295536"></a><a name="b1632011295536"></a>dev</strong>: structure pointer to the SDIO device controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p37916441244"><a name="p37916441244"></a><a name="p37916441244"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p97911044948"><a name="p97911044948"></a><a name="p97911044948"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1792184413412"><a name="p1792184413412"></a><a name="p1792184413412"></a>Releases the exclusively claimed host.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>CommonInfo includes the following information:
>- **maxBlockNum**: specifies the maximum number of blocks in a request.
>- **maxBlockSize**: specifies the maximum number of bytes in a block.
>- **maxRequestSize**: specifies the maximum number of bytes in a request.
>- **enTimeout**: specifies the maximum timeout period, in milliseconds.
>- **funcNum**: specifies the function number, which ranges from **1** to **7**.
>- **irqCap**: specifies the interrupt request \(IRQ\) capabilities.
>- **\(void \*\)data**
## How to Develop<a name="section581179475150053"></a>
**Table 1** Description of the callback functions in SdioDeviceOps
| Function| Input Parameter| Output Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| incrAddrReadBytes | **dev**: structure pointer to the SDIO device controller.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to read, which is of the uint32_t type.| **data**: pointer to the output value, which is of the uint8_t type.| HDF_STATUS| Incrementally reads data of a given length from the specified SDIO address.|
| incrAddrWriteBytes | **dev**: structure pointer to the SDIO device controller.<br>**data**: pointer to the input value, which is of the uint8_t type.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to write, which is of the uint32_t type.| –| HDF_STATUS| Incrementally writes data of a given length to the specified SDIO address.|
| fixedAddrReadBytes | **dev**: structure pointer to the SDIO device controller.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to read, which is of the uint32_t type.<br>**scatterLen**: data length, which is of the uint32_t type.| **data**: pointer to the output value, which is of the uint8_t type.| HDF_STATUS| Reads data of a given length from a fixed SDIO address.|
| fixedAddrWriteBytes | **dev**: structure pointer to the SDIO device controller.<br>**data**: pointer to the input value, which is of the uint8_t type.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to write, which is of the uint32_t type.<br>**scatterLen**: data length, which is of the uint32_t type.| –| HDF_STATUS| Writes data of a given length to the fixed SDIO address.|
| func0ReadBytes | **dev**: structure pointer to the SDIO device controller.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to read, which is of the uint32_t type.| **data**: pointer to the output value, which is of the uint8_t type.| HDF_STATUS| Reads data of a given length from the address space of SDIO function 0.|
| func0WriteBytes | **dev**: structure pointer to the SDIO device controller.<br>**data**: pointer to the input value, which is of the uint8_t type.<br>**addr**: SDIO address, which is of the uint32_t type.<br>**size**: size of the data to write, which is of the uint32_t type.| –| HDF_STATUS| Writes data of a given length to the address space of SDIO function 0.|
| setBlockSize | **dev**: structure pointer to the SDIO device controller.<br>**blockSize**: block size, which is of the uint32_t type.| –| HDF_STATUS| Sets the block size.|
| getCommonInfo | **dev**: structure pointer to the SDIO device controller. <br>**infoType**: info type, which is of the uint32_t type.| **info**: structure pointer to the output **SdioFuncInfo**.| HDF_STATUS| Obtains **CommonInfo**. For details, see the **NOTE** below this table.|
| setCommonInfo | **dev**: structure pointer to the SDIO device controller.<br>**info**: union pointer to the input **SdioFuncInfo**.<br>**infoType**: info type, which is of the uint32_t type.| –| HDF_STATUS| Sets **CommonInfo**. For details, see the **NOTE** below this table.|
| flushData | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Called to flush data when the SDIO device needs to be re-initialized or an error occurs.|
| enableFunc | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Enables an SDIO device.|
| disableFunc | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Disables an SDIO device.|
| claimIrq | **dev**: structure pointer to the SDIO device controller.<br>**irqHandler**: void function pointer to the interrupt request (IRQ) handler.| –| HDF_STATUS| Claims an SDIO IRQ.|
| releaseIrq | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Releases an SDIO IRQ.|
| findFunc | **dev**: structure pointer to the SDIO device controller.<br>**configData**: structure pointer to the key SDIO function information.| –| HDF_STATUS| Obtains the matching funcNum.|
| claimHost | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Claims a host exclusively.|
| releaseHost | **dev**: structure pointer to the SDIO device controller.| –| HDF_STATUS| Releases the exclusively claimed host.|
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> CommonInfo includes the following information:<br>- **maxBlockNum**: specifies the maximum number of blocks in a request. <br>- **maxBlockSize**: specifies the maximum number of bytes in a block. <br>- **maxRequestSize**: specifies the maximum number of bytes in a request. <br>- **enTimeout**: specifies the maximum timeout period, in milliseconds. <br>- **funcNum**: specifies the function number, which ranges from 1 to 7. <br>- **irqCap**: specifies the IRQ capabilities. <br>- **(void \*)data**
## How to Develop
The SDIO module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **sdio\_config.hcs** file.
3. Instantiate the SDIO controller object.
- Initialize **SdioDevice**.
- Instantiate **SdioDeviceOps** in the **SdioDevice** object.
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>For details, see [Available APIs](#available-apis).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the SDIO control status and response to interrupts.
## Development Example<a name="section2112250242150053"></a>
The following uses **sdio\_adapter.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
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, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exit.
- SDIO driver entry reference
```
struct HdfDriverEntry g_sdioDriverEntry = {
.moduleVersion = 1,
.Bind = Hi35xxLinuxSdioBind, // See the Bind function.
.Init = Hi35xxLinuxSdioInit, // See the Init function.
.Release = Hi35xxLinuxSdioRelease// See the Release function.
.moduleName = "HDF_PLATFORM_SDIO",// (Mandatory) The value must be the same as that of moduleName in the **.hcs** file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_sdioDriverEntry);
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **sdio\_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 **SdioDevice** members at the core layer.
In this example, there is only one SDIO controller. If there are multiple SDIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **sdio\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_sdio :: device {
device0 :: deviceNode {
policy = 1;
priority = 70;
permission = 0644;
moduleName = "HDF_PLATFORM_SDIO"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HDF_PLATFORM_MMC_2"; // (Mandatory) Unique name of the service published by the driver
deviceMatchAttr = "hisilicon_hi35xx_sdio_0";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller in sdio_config.hcs.
}
}
}
}
}
```
- **sdio\_config.hcs** configuration reference
```
root {
platform {
sdio_config {
template sdio_controller {
match_attr = "";
hostId = 2; // (Mandatory) Set the value to 2. For details, see mmc_config.hcs.
devType = 2; // (Mandatory) Set the value to 2. For details, see mmc_config.hcs.
}
controller_0x2dd1 :: sdio_controller {
match_attr = "hisilicon_hi35xx_sdio_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
}
}
}
```
3. Initialize the **SdioDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **SdioDeviceOps** \(used to call underlying functions of the driver\) in **SdioDevice**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
- Custom structure reference
To the driver, the custom structure carries parameters and data. The values in the **sdio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also passed to the objects at the core layer.
```
typedef struct {
uint32_t maxBlockNum; // Maximum number of blocks in a request.
uint32_t maxBlockSize; // Maximum number of bytes in a block. The value range is 1 to 2048.
uint32_t maxRequestSize; // Maximum number of bytes in a request. The value range is 1 to 2048.
uint32_t enTimeout; // Maximum timeout period in milliseconds. The value cannot exceed one second.
uint32_t funcNum; // Function number, which ranges from 1 to 7.
uint32_t irqCap; // IRQ capabilities.
void *data; // Private data.
} SdioFuncInfo;
// SdioDevice is the core layer controller structure. Its members are assigned with values by using the Bind function.
struct SdioDevice {
struct SdDevice sd;
struct SdioDeviceOps *sdioOps;
struct SdioRegister sdioReg;
uint32_t functions;
struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER];
struct SdioFunction *curFunction;
struct OsalThread thread; /* irq thread */
struct OsalSem sem;
bool irqPending;
bool threadRunning;
};
```
- Instantiate the callback function structure **SdioDeviceOps** in **SdioDevice**. Other members are initialized by using the **Init** function.
```
static struct SdioDeviceOps g_sdioDeviceOps = {
.incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes,
.incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes,
.fixedAddrReadBytes = Hi35xxLinuxSdioFixedAddrReadBytes,
.fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes,
.func0ReadBytes = Hi35xxLinuxSdioFunc0ReadBytes,
.func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes,
.setBlockSize = Hi35xxLinuxSdioSetBlockSize,
.getCommonInfo = Hi35xxLinuxSdioGetCommonInfo,
.setCommonInfo = Hi35xxLinuxSdioSetCommonInfo,
.flushData = Hi35xxLinuxSdioFlushData,
.enableFunc = Hi35xxLinuxSdioEnableFunc,
.disableFunc = Hi35xxLinuxSdioDisableFunc,
.claimIrq = Hi35xxLinuxSdioClaimIrq,
.releaseIrq = Hi35xxLinuxSdioReleaseIrq,
.findFunc = Hi35xxLinuxSdioFindFunc,
.claimHost = Hi35xxLinuxSdioClaimHost,
.releaseHost = Hi35xxLinuxSdioReleaseHost,
};
```
- Bind function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the **.hcs** configuration file information.
Return values:
HDF\_STATUS \(The following table lists some status. For details about other status, see **HDF\_STATUS** in the **//drivers/framework/include/utils/hdf\_base.h** file.\)
**Table 2** Input parameters and return values of the Bind function
<a name="table297118388199"></a>
<table><thead align="left"><tr id="row197133831916"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1972138191917"><a name="p1972138191917"></a><a name="p1972138191917"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p197213387192"><a name="p197213387192"></a><a name="p197213387192"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row20972538191911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p99721238181910"><a name="p99721238181910"></a><a name="p99721238181910"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1097243811914"><a name="p1097243811914"></a><a name="p1097243811914"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row5972203811199"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16972838151919"><a name="p16972838151919"></a><a name="p16972838151919"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1397223817192"><a name="p1397223817192"></a><a name="p1397223817192"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row14972173831913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7972538131919"><a name="p7972538131919"></a><a name="p7972538131919"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p15972138191913"><a name="p15972138191913"></a><a name="p15972138191913"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row59721938131918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p199733380196"><a name="p199733380196"></a><a name="p199733380196"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p179731038101914"><a name="p179731038101914"></a><a name="p179731038101914"></a>I/O error</p>
</td>
</tr>
<tr id="row1797316382198"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16973203812195"><a name="p16973203812195"></a><a name="p16973203812195"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p297318386196"><a name="p297318386196"></a><a name="p297318386196"></a>Initialization successful</p>
</td>
</tr>
<tr id="row16973838151918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1497353819191"><a name="p1497353819191"></a><a name="p1497353819191"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p109732038171917"><a name="p109732038171917"></a><a name="p109732038171917"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **SdioCntlr**, calls the **SdioCntlrAdd** function at the core layer, and performs other initialization operations customized by the vendor.
```
static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
int32_t ret;
...
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// Apply for memory.
...
cntlr->ops = &g_sdioCntlrOps; // (Mandatory) struct MmcCntlrOps g_sdioCntlrOps={
// .rescanSdioDev = Hi35xxLinuxSdioRescan,};
cntlr->hdfDevObj = obj; // (Mandatory) Enable conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Enable conversion between HdfDeviceObject and MmcCntlr.
ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);// (Mandatory) Initialize the index and devType of cntlr. If the initialization fails, execute goto _ERR.
...
ret = MmcCntlrAdd(cntlr); // (Mandatory) Call the mmc_core.c function at the core layer. If the function fails to be called, execute goto _ERR.
...
ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);// (Mandatory) Call the mmc_core.c function at the core layer. If the function fails to be called, execute goto _ERR.
...
MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);// (Mandatory) Call the function of mmc_core.c at the core layer to instantiate the hook.
HDF_LOGD("Hi35xxLinuxSdioBind: Success!");
return HDF_SUCCESS;
_ERR:
Hi35xxLinuxSdioDeleteCntlr(cntlr);
HDF_LOGE("Hi35xxLinuxSdioBind: Fail!");
return HDF_FAILURE;
}
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the **.hcs** configuration file information.
Return values:
HDF\_STATUS
Function description:
No operation. The vendor can add operations as required.
```
static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
{
(void)obj;// No operation. The vendor can add operations as required.
HDF_LOGD("Hi35xxLinuxSdioInit: Success!");
return HDF_SUCCESS;
}
```
- Release function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the **.hcs** configuration file information.
Return values:
Function description:
Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Bind** function has the corresponding value assignment operations.
```
static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj)
{
if (obj == NULL) {
return;
}
Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);// (Mandatory) Custom function for releasing memory. A forced conversion from HdfDeviceObject to MmcCntlr is involved.
}
```
\ No newline at end of file
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **sdio_config.hcs** file.
3. Instantiate the SDIO controller object.
- Initialize **SdioDevice**.
- Instantiate **SdioDeviceOps** in the **SdioDevice** object.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> For details about the functions in **SdioDeviceOps**, see [Available APIs](#available-apis).
4. Debug the driver.
(Optional) For new drivers, verify the basic functions, such as the SDIO control status and response to interrupts.
## Development Example
The following uses **sdio_adapter.c** as an example to present the information required for implementing device functions.
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.
SDIO driver entry example:
```
struct HdfDriverEntry g_sdioDriverEntry = {
.moduleVersion = 1,
.Bind = Hi35xxLinuxSdioBind, // See the Bind function.
.Init = Hi35xxLinuxSdioInit, // See the Init function.
.Release = Hi35xxLinuxSdioRelease, // See the Release function.
.moduleName = "HDF_PLATFORM_SDIO",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF.
HDF_INIT(g_sdioDriverEntry);
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **sdio_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 **SdioDevice** members at the core layer.
In this example, there is only one SDIO controller. If there are multiple SDIO controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **sdio_config** file for each controller.
- **device_info.hcs** configuration example:
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_sdio :: device {
device0 :: deviceNode {
policy = 1;
priority = 70;
permission = 0644;
moduleName = "HDF_PLATFORM_SDIO"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HDF_PLATFORM_MMC_2"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hisilicon_hi35xx_sdio_0";// (Mandatory) Private data of the controller. The value must be the same as the controller information in sdio_config.hcs.
}
}
}
}
}
```
- **sdio_config.hcs** configuration example:
```
root {
platform {
sdio_config {
template sdio_controller {
match_attr = "";
hostId = 2; // (Mandatory) The value must be 2. For details, see mmc_config.hcs.
devType = 2; // (Mandatory) The value must be 2. For details, see mmc_config.hcs.
}
controller_0x2dd1 :: sdio_controller {
match_attr = "hisilicon_hi35xx_sdio_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
}
}
}
```
3. Initialize the **SdioDevice** 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 **SdioDeviceOps** in **SdioDevice** (so that the underlying driver functions can be called).
- 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 **sdio_config.hcs** file to initialize the members in the custom structure and passes important parameters to the object at the core layer.
```
typedef struct {
uint32_t maxBlockNum; // Maximum number of blocks in a request.
uint32_t maxBlockSize; // Maximum number of bytes in a block. The value range is 1 to 2048.
uint32_t maxRequestSize; // Maximum number of bytes in a request. The value range is 1 to 2048.
uint32_t enTimeout; // Maximum timeout period in milliseconds. The value cannot exceed one second.
uint32_t funcNum; // Function number, which ranges from 1 to 7.
uint32_t irqCap; // IRQ capabilities.
void *data; // Private data.
} SdioFuncInfo;
// SdioDevice is the core layer controller structure. The Bind function assigns values to the members of SdioDevice.
struct SdioDevice {
struct SdDevice sd;
struct SdioDeviceOps *sdioOps;
struct SdioRegister sdioReg;
uint32_t functions;
struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER];
struct SdioFunction *curFunction;
struct OsalThread thread; /* irq thread */
struct OsalSem sem;
bool irqPending;
bool threadRunning;
};
```
- Instantiating **SdioDeviceOps** in **SdioDevice** (other members are initialized by **Init**)
```
static struct SdioDeviceOps g_sdioDeviceOps = {
.incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes,
.incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes,
.fixedAddrReadBytes = Hi35xxLinuxSdioFixedAddrReadBytes,
.fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes,
.func0ReadBytes = Hi35xxLinuxSdioFunc0ReadBytes,
.func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes,
.setBlockSize = Hi35xxLinuxSdioSetBlockSize,
.getCommonInfo = Hi35xxLinuxSdioGetCommonInfo,
.setCommonInfo = Hi35xxLinuxSdioSetCommonInfo,
.flushData = Hi35xxLinuxSdioFlushData,
.enableFunc = Hi35xxLinuxSdioEnableFunc,
.disableFunc = Hi35xxLinuxSdioDisableFunc,
.claimIrq = Hi35xxLinuxSdioClaimIrq,
.releaseIrq = Hi35xxLinuxSdioReleaseIrq,
.findFunc = Hi35xxLinuxSdioFindFunc,
.claimHost = Hi35xxLinuxSdioClaimHost,
.releaseHost = Hi35xxLinuxSdioReleaseHost,
};
```
- **Bind** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**HDF_STATUS**
The table below describes some status. For more information, see **HDF_STATUS** in the **/drivers/framework/include/utils/hdf_base.h** file.
**Table 2** Description of HDF_STATUS
| Status | Description |
| ---------------------- | -------------------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object. |
| 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 object and **SdioCntlr**, calls the **SdioCntlrAdd** function at the core layer, and performs other initialization operations customized by the vendor.
```
static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
{
struct MmcCntlr *cntlr = NULL;
int32_t ret;
...
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// Allocate memory.
...
cntlr->ops = &g_sdioCntlrOps; // (Mandatory) struct MmcCntlrOps g_sdioCntlrOps={
// .rescanSdioDev = Hi35xxLinuxSdioRescan,};
cntlr->hdfDevObj = obj; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and MmcCntlr.
ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj); // (Mandatory) Initialize index and devType of cntlr. If the initialization fails, execute goto _ERR.
...
ret = MmcCntlrAdd(cntlr); // (Mandatory) Call the function in mmc_core.c. If the operation fails, execute goto _ERR.
...
ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType); // (Mandatory) Call the function in mmc_core.c. If the operation fails, execute goto _ERR.
...
MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps); // (Mandatory) Call the function in mmc_core.c to hook the related functions.
HDF_LOGD("Hi35xxLinuxSdioBind: Success!");
return HDF_SUCCESS;
_ERR:
Hi35xxLinuxSdioDeleteCntlr(cntlr);
HDF_LOGE("Hi35xxLinuxSdioBind: Fail!");
return HDF_FAILURE;
}
```
- **Init** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
**HDF_STATUS**
**Function description**:
You can add operations as required.
```
static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
{
(void)obj;// No operation. You can add operations as required.
HDF_LOGD("Hi35xxLinuxSdioInit: Success!");
return HDF_SUCCESS;
}
```
- **Release** function
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**Return value**:
No value is returned.
**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.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Bind** function has the corresponding value assignment operations.
```
static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj)
{
if (obj == NULL) {
return;
}
Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service);// (Mandatory) Custom function for releasing memory. A forced conversion from HdfDeviceObject to MmcCntlr is involved.
}
```
......@@ -53,7 +53,8 @@ The SPI module adaptation involves the following steps:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> 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.
......@@ -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.
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.
SPI driver entry example:
SPI driver entry example:
```
struct HdfDriverEntry g_hdfSpiDevice = {
......@@ -78,12 +84,12 @@ The following uses **spi_hi35xx.c** as an example to present the information req
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.
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
......@@ -124,22 +130,22 @@ The following uses **spi_hi35xx.c** as an example to present the information req
```
root {
platform {
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.
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.
serviceName = "";
match_attr = "";
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.
clkRate = 100000000;
bitsPerWord = 8 // Number of bits per word.
mode = 19; // SPI data input/output mode.
maxSpeedHz = 0; // Maximum clock frequency.
minSpeedHz = 0; // Minimum clock frequency.
speed = 2000000; // Current message transfer speed.
fifoSize = 256; // FIFO size.
numCs = 1; // Chip select (CS) number.
regBase = 0x120c0000; // Used for address mapping.
irqNum = 100; // Interrupt request (IRQ) number.
bitsPerWord = 8; // Number of bits per word.
mode = 19; // SPI data input/output mode.
maxSpeedHz = 0; // Maximum clock frequency.
minSpeedHz = 0; // Minimum clock frequency.
speed = 2000000; // Current message transfer speed.
fifoSize = 256; // FIFO size.
numCs = 1; // Chip select (CS) number.
regBase = 0x120c0000; // Used for address mapping.
irqNum = 100; // Interrupt request (IRQ) number.
REG_CRG_SPI = 0x120100e4; // CRG_REG_BASE(0x12010000) + 0x0e4
CRG_SPI_CKEN = 0;
CRG_SPI_RST = 0;
......@@ -148,9 +154,9 @@ The following uses **spi_hi35xx.c** as an example to present the information req
MISC_CTRL_SPI_CS_SHIFT = 0;
}
controller_0x120c0000 :: spi_controller {
busNum = 0; // (Mandatory) Bus number.
CRG_SPI_CKEN = 0x10000; // (0x1 << 16) 0:close clk, 1:open clk
CRG_SPI_RST = 0x1; // (0x1 << 0) 0:cancel reset, 1:reset
busNum = 0; // (Mandatory) Bus number.
CRG_SPI_CKEN = 0x10000; // (0x1 << 16) 0:close clk, 1:open clk
CRG_SPI_RST = 0x1; // (0x1 << 0) 0:cancel reset, 1:reset
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 {
......@@ -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.
}
}
}
```
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
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 SpiCntlr *cntlr;
......@@ -231,15 +238,15 @@ The following uses **spi_hi35xx.c** as an example to present the information req
- **Bind** function
Input parameter:
**Input parameter**:
**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**.
......@@ -253,14 +260,14 @@ The following uses **spi_hi35xx.c** as an example to present the information req
struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device)
{
struct SpiCntlr *cntlr = NULL; // Create the SpiCntlr object at the core layer.
struct SpiCntlr *cntlr = NULL; // Create an SpiCntlr object.
...
cntlr = (struct SpiCntlr *)OsalMemCalloc(sizeof(*cntlr));// Allocate memory.
...
cntlr->device = device; // 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.
DListHeadInit(&cntlr->list); // Add the corresponding nodes.
cntlr->device = device; // 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.
DListHeadInit(&cntlr->list); // Add nodes.
cntlr->priv = NULL;
return cntlr;
}
......@@ -268,17 +275,15 @@ The following uses **spi_hi35xx.c** as an example to present the information req
- **Init** function
Input parameter:
**Input parameter**:
**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** HDF_STATUS
**Table 2** Description of HDF_STATUS
| Status| Description|
| -------- | -------- |
......@@ -289,10 +294,10 @@ The following uses **spi_hi35xx.c** as an example to present the information req
| HDF_SUCCESS | Initialization successful.|
| HDF_FAILURE | Initialization failed.|
Function description:
**Function description**:
Initializes the custom structure object and **SpiCntlr**.
```
static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device)
......@@ -300,10 +305,10 @@ The following uses **spi_hi35xx.c** as an example to present the information req
int32_t ret;
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.
// return (device == NULL) ? NULL : (struct SpiCntlr *)device->service;
...
ret = Pl022Init(cntlr, device); // (Mandatory) Instantiate the operation object customized by the vendor. The following is an example:
ret = Pl022Init(cntlr, device); // (Mandatory) Instantiate the custom operation object. The following is an example:
...
ret = Pl022Probe(cntlr->priv);
...
......@@ -317,9 +322,9 @@ The following uses **spi_hi35xx.c** as an example to present the information req
...
pl022 = (struct Pl022 *)OsalMemCalloc(sizeof(*pl022));// Request memory.
...
ret = SpiGetBaseCfgFromHcs(pl022, device->property); // Initialize busNum, numCs, speed, fifoSize, clkRate, mode, bitsPerWord, and transferMode.
ret = SpiGetBaseCfgFromHcs(pl022, device->property); // Initialize busNum, numCs, speed, fifoSize, clkRate, mode, bitsPerWord, and transferMode.
...
ret = SpiGetRegCfgFromHcs(pl022, device->property); // Initialize regBase, phyBase, irqNum, regCrg, clkEnBit, clkRstBit, regMiscCtrl, miscCtrlCs, and miscCtrlCsShift.
ret = SpiGetRegCfgFromHcs(pl022, device->property); // Initialize regBase, phyBase, irqNum, regCrg, clkEnBit, clkRstBit, regMiscCtrl, regMiscCtrl, miscCtrlCs, and miscCtrlCsShift.
...
// Calculate the frequencies corresponding to the maximum and minimum speeds.
pl022->maxSpeedHz = (pl022->clkRate) / ((SCR_MIN + 1) * CPSDVSR_MIN);
......@@ -338,20 +343,22 @@ The following uses **spi_hi35xx.c** as an example to present the information req
return 0;
}
```
- **Release** function
Input parameter:
**Input parameter**:
**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 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.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> 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
{
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.
// return (device==NULL) ?NULL:(struct SpiCntlr *)device->service;
cntlr = SpiCntlrFromDevice(device); // Forced conversion from HdfDeviceObject to SpiCntlr is involved. For details about the value assignment, see the Bind function.
// return (device==NULL) ?NULL:(struct SpiCntlr *)device->service;
...
if (cntlr->priv != NULL) {
Pl022Remove((struct Pl022 *)cntlr->priv);// A forced conversion from SpiCntlr to Pl022 is involved.
......
# UART<a name="EN-US_TOPIC_0000001160652800"></a>
# UART
## Overview<a name="section833012453535"></a>
The Universal Asynchronous Receiver/Transmitter \(UART\) is a universal serial data bus used for asynchronous communication. It enables bi-directional communication between devices in full-duplex mode.
## Overview
The Universal Asynchronous Receiver/Transmitter (UART) is a universal serial data bus used for asynchronous communication. It enables bi-directional communication between devices in full-duplex mode.
UART is widely used to print information for debugging or to connect to various external modules such as GPS and Bluetooth.
A UART is connected to other modules through two wires \(as shown in [Figure 1](#fig68294715408)\) or four wires \(as shown in [Figure 2](#fig179241542163112)\).
- TX: TX pin of the transmitting UART. It is connected to the RX pin of the peer UART.
- RX: RX pin of the receiving UART. It is connected to the TX pin of the peer UART.
- RTS: Request to Send signal pin. It is connected to the CTS pin of the peer UART and is used to indicate whether the local UART is ready to receive data.
- CTS: Clear to Send signal pin. It is connected to the RTS pin of the peer UART and is used to indicate whether the local UART is allowed to send data to the peer end.
**Figure 1** 2-wire UART communication<a name="fig68294715408"></a>
![](figures/2-wire-uart-communication.png "2-wire-uart-communication")
**Figure 2** 4-wire UART communication<a name="fig179241542163112"></a>
![](figures/4-wire-uart-communication.png "4-wire-uart-communication")
The transmitting and receiving UARTs must ensure that they have the same settings on particular attributes such as the baud rate and data format \(start bit, data bit, parity bit, and stop bit\) before they start to communicate. During data transmission, a UART sends data to the peer end over the TX pin and receives data from the peer end over the RX pin. When the size of the buffer used by a UART for storing received data reaches the preset threshold, the RTS signal of the UART changes to **1** \(data cannot be received\), and the peer UART stops sending data to it because its CTS signal does not allow it to send data.
## Available APIs<a name="section1928742202715"></a>
The UART interface defines a set of common functions for operating a UART port, including obtaining and releasing device handles, reading and writing data of a specified length, and obtaining and setting the baud rate, as well as the device attributes.
**Table 1** APIs for the UART driver
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row1223152681611"><th class="cellrowborder" valign="top" width="26.619999999999997%" id="mcps1.2.4.1.1"><p id="p210413571619"><a name="p210413571619"></a><a name="p210413571619"></a><strong id="b4100105545211"><a name="b4100105545211"></a><a name="b4100105545211"></a>Capability</strong></p>
</th>
<th class="cellrowborder" valign="top" width="31.369999999999997%" id="mcps1.2.4.1.2"><p id="p810403511614"><a name="p810403511614"></a><a name="p810403511614"></a><strong id="b1653121711186"><a name="b1653121711186"></a><a name="b1653121711186"></a>Function</strong></p>
</th>
<th class="cellrowborder" valign="top" width="42.01%" id="mcps1.2.4.1.3"><p id="p110418354161"><a name="p110418354161"></a><a name="p110418354161"></a><strong id="b69108168153412"><a name="b69108168153412"></a><a name="b69108168153412"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row1638573613415"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p917154316414"><a name="p917154316414"></a><a name="p917154316414"></a>Obtaining and releasing device handles</p>
<p id="p9596111154212"><a name="p9596111154212"></a><a name="p9596111154212"></a></p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p20385163614412"><a name="p20385163614412"></a><a name="p20385163614412"></a>UartOpen</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p12101135184213"><a name="p12101135184213"></a><a name="p12101135184213"></a>Obtains the UART device handle.</p>
</td>
</tr>
<tr id="row5950143316415"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p149501733134113"><a name="p149501733134113"></a><a name="p149501733134113"></a>UartClose</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p371073520422"><a name="p371073520422"></a><a name="p371073520422"></a>Releases a specified UART device handle.</p>
</td>
</tr>
<tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>Reading and writing data</p>
<p id="p131072201215"><a name="p131072201215"></a><a name="p131072201215"></a></p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p8296182221219"><a name="p8296182221219"></a><a name="p8296182221219"></a>UartRead</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p16297172213125"><a name="p16297172213125"></a><a name="p16297172213125"></a>Reads data of a specified length from a UART device.</p>
</td>
</tr>
<tr id="row11585016539"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1095722493616"><a name="p1095722493616"></a><a name="p1095722493616"></a>UartWrite</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p15297162215122"><a name="p15297162215122"></a><a name="p15297162215122"></a>Writes data of a specified length into a UART device.</p>
</td>
</tr>
<tr id="row8687115843715"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p196317143813"><a name="p196317143813"></a><a name="p196317143813"></a>Obtaining and setting the baud rate</p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p166885582375"><a name="p166885582375"></a><a name="p166885582375"></a>UartGetBaud</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p13688358183716"><a name="p13688358183716"></a><a name="p13688358183716"></a>Obtains the UART baud rate.</p>
</td>
</tr>
<tr id="row18987529382"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p698719214383"><a name="p698719214383"></a><a name="p698719214383"></a>UartSetBaud</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1398712123810"><a name="p1398712123810"></a><a name="p1398712123810"></a>Sets the UART baud rate.</p>
</td>
</tr>
<tr id="row1551850115317"><td class="cellrowborder" rowspan="2" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p1629782201218"><a name="p1629782201218"></a><a name="p1629782201218"></a>Obtaining and setting device attributes</p>
<p id="p10308192211216"><a name="p10308192211216"></a><a name="p10308192211216"></a></p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p32972022151218"><a name="p32972022151218"></a><a name="p32972022151218"></a>UartGetAttribute</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p13297122216123"><a name="p13297122216123"></a><a name="p13297122216123"></a>Obtains the UART device attributes.</p>
</td>
</tr>
<tr id="row7545065311"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p102974224120"><a name="p102974224120"></a><a name="p102974224120"></a>UartSetAttribute</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p152971322111219"><a name="p152971322111219"></a><a name="p152971322111219"></a>Sets the UART device attributes.</p>
</td>
</tr>
<tr id="row14614115403"><td class="cellrowborder" valign="top" width="26.619999999999997%" headers="mcps1.2.4.1.1 "><p id="p1746281144010"><a name="p1746281144010"></a><a name="p1746281144010"></a>Setting the transmission mode</p>
</td>
<td class="cellrowborder" valign="top" width="31.369999999999997%" headers="mcps1.2.4.1.2 "><p id="p1146215112405"><a name="p1146215112405"></a><a name="p1146215112405"></a>UartSetTransMode</p>
</td>
<td class="cellrowborder" valign="top" width="42.01%" headers="mcps1.2.4.1.3 "><p id="p11303181216414"><a name="p11303181216414"></a><a name="p11303181216414"></a>Sets the UART transmission mode.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE**<br>
>All functions provided in this document can be called only in kernel space.
## Usage Guidelines<a name="section12779050105412"></a>
### How to Use<a name="section1858116395510"></a>
A UART is connected to other modules through two wires (as shown in Figure 1) or four wires (as shown in Figure 2).
- TX: TX pin of the transmitting UART. It is connected to the RX pin of the peer UART.
- RX: RX pin of the receiving UART. It is connected to the TX pin of the peer UART.
- RTS: Request to Send signal pin. It is connected to the CTS pin of the peer UART and is used to indicate whether the local UART is ready to receive data.
- CTS: Clear to Send signal pin. It is connected to the RTS pin of the peer UART and is used to indicate whether the local UART is allowed to send data to the peer end.
**Figure 1** Two-wire UART communication
![](figures/2-wire-uart-communication.png "2-wire-uart-communication")
**Figure 2** Four-wire UART communication
![](figures/4-wire-uart-communication.png "4-wire-uart-communication")
- The transmitting and receiving UARTs must ensure that they have the same settings on particular attributes such as the baud rate and data format (start bit, data bit, parity bit, and stop bit) before they start to communicate. During data transmission, a UART sends data to the peer end over the TX pin and receives data from the peer end over the RX pin. When the size of the buffer used by a UART for storing received data reaches the preset threshold, the RTS signal of the UART changes to **1** (data cannot be received), and the peer UART stops sending data to it because its CTS signal does not allow it to send data.
- The UART interface defines a set of common functions for operating a UART port, including obtaining and releasing device handles, reading and writing data of a specified length, and obtaining and setting the baud rate, as well as the device attributes.
## Available APIs
**Table 1** UART driver APIs
| API| Description|
| -------- | -------- |
| UartOpen | Obtains a UART device handle.|
| UartClose | Releases a UART device handle.|
| UartRead | Reads data of the specified length from a UART device.|
| UartWrite | Writes data of the specified length to a UART device.|
| UartGetBaud | Obtains the UART baud rate.|
| UartSetBaud | Sets the UART baud rate.|
| UartGetAttribute | Obtains UART device attributes.|
| UartSetAttribute | Sets UART device attributes.|
| UartSetTransMode | Sets the UART transmission mode.|
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> All APIs described in this document can be called only in kernel mode.
## Usage Guidelines
### How to Use
The figure below illustrates how to use the APIs.
**Figure 3** Using UART driver APIs<a name="fig99673244388"></a>
![](figures/using-UART-process.png "process-of-using-a-uart-device")
### Obtaining a UART Device Handle<a name="section124512065617"></a>
Before performing UART communication, call **UartOpen** to obtain a UART device handle. This function returns the pointer to the UART device handle with a specified port number.
DevHandle UartOpen\(uint32\_t port\);
**Table 2** Description of UartOpen
<a name="table14222165114310"></a>
<table><thead align="left"><tr id="row1022175133111"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p13221551153117"><a name="p13221551153117"></a><a name="p13221551153117"></a><strong id="b538194163718"><a name="b538194163718"></a><a name="b538194163718"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p122211251103111"><a name="p122211251103111"></a><a name="p122211251103111"></a><strong id="b20924204203714"><a name="b20924204203714"></a><a name="b20924204203714"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row6222451133114"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p92221518315"><a name="p92221518315"></a><a name="p92221518315"></a>port</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1322217518318"><a name="p1322217518318"></a><a name="p1322217518318"></a>UART port number.</p>
</td>
</tr>
<tr id="row1122245153112"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p102221451123118"><a name="p102221451123118"></a><a name="p102221451123118"></a><strong id="b101754483378"><a name="b101754483378"></a><a name="b101754483378"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1122215143113"><a name="p1122215143113"></a><a name="p1122215143113"></a><strong id="b647184919374"><a name="b647184919374"></a><a name="b647184919374"></a>Description</strong></p>
</td>
</tr>
<tr id="row522275114317"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p422235114313"><a name="p422235114313"></a><a name="p422235114313"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p5222351203112"><a name="p5222351203112"></a><a name="p5222351203112"></a>Failed to obtain the UART device handle.</p>
</td>
</tr>
<tr id="row1222212513311"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p5222125115316"><a name="p5222125115316"></a><a name="p5222125115316"></a>Device handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p192228515311"><a name="p192228515311"></a><a name="p192228515311"></a>UART device handle.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to obtain a UART device handle based on the assumption that the UART port number is **3**:
```
DevHandle handle = NULL; /* The UART device handle */
uint32_t port = 3; /* UART port number */
**Figure 3** Using UART driver APIs
![](figures/using-UART-process.png)
### Opening a UART Device Handle
Before performing UART communication, call **UartOpen** to obtain a UART device handle. This function returns the pointer to the UART device handle with the specified port number.
```
DevHandle UartOpen(uint32_t port);
```
**Table 2** Description of UartOpen
| Parameter| Description|
| -------- | -------- |
| port | UART port number.|
| **Return Value**| **Description**|
| NULL | The operation failed.|
| Device handle| The operation is successful. The obtained UART device handle is returned.|
Example: Obtain the device handle of UART port 3.
```
DevHandle handle = NULL; /* UART device handle */
uint32_t port = 3; /* UART port number */
handle = UartOpen(port);
if (handle == NULL) {
HDF_LOGE("UartOpen: failed!\n");
......@@ -158,51 +88,29 @@ if (handle == NULL) {
}
```
### Setting the UART Baud Rate<a name="section86881004579"></a>
After obtaining the UART device handle, set the UART baud rate by calling the following function:
int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\);
**Table 3** Description of UartSetBaud
<a name="table539135313325"></a>
<table><thead align="left"><tr id="row15391205311323"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p11390453103216"><a name="p11390453103216"></a><a name="p11390453103216"></a><strong id="b0704124143717"><a name="b0704124143717"></a><a name="b0704124143717"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p839065316328"><a name="p839065316328"></a><a name="p839065316328"></a><strong id="b10127164520376"><a name="b10127164520376"></a><a name="b10127164520376"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row2039115373216"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1639165310324"><a name="p1639165310324"></a><a name="p1639165310324"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p539115320328"><a name="p539115320328"></a><a name="p539115320328"></a>UART device handle.</p>
</td>
</tr>
<tr id="row163911753143214"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13911653203215"><a name="p13911653203215"></a><a name="p13911653203215"></a>baudRate</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p163919537322"><a name="p163919537322"></a><a name="p163919537322"></a>Baud rate of the UART to set.</p>
</td>
</tr>
<tr id="row539155343218"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1039185313321"><a name="p1039185313321"></a><a name="p1039185313321"></a><strong id="b1551834812373"><a name="b1551834812373"></a><a name="b1551834812373"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p123911753143213"><a name="p123911753143213"></a><a name="p123911753143213"></a><strong id="b43667492373"><a name="b43667492373"></a><a name="b43667492373"></a>Description</strong></p>
</td>
</tr>
<tr id="row2391853153218"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17391185310322"><a name="p17391185310322"></a><a name="p17391185310322"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14391653193210"><a name="p14391653193210"></a><a name="p14391653193210"></a>Succeeded in setting the UART baud rate.</p>
</td>
</tr>
<tr id="row23912053143211"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7391165320321"><a name="p7391165320321"></a><a name="p7391165320321"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p639185318322"><a name="p639185318322"></a><a name="p639185318322"></a>Failed to set the UART baud rate.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to set the UART baud rate to **9600**:
### Setting the UART Baud Rate
Call **UartSetBaud()** to set the UART baud rate.
```
int32_t UartSetBaud(DevHandle handle, uint32_t baudRate);
```
**Table 3** Description of UartSetBaud
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| baudRate | Baud rate to set.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Example: Set the UART baud rate to **9600**.
```
int32_t ret;
/* Set the UART baud rate to 9600. */
......@@ -212,51 +120,29 @@ if (ret != 0) {
}
```
### Obtaining the UART Baud Rate<a name="section897032965712"></a>
After setting the UART baud rate, obtain the current baud rate by calling the following function:
int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\);
**Table 4** Description of UartGetBaud
<a name="table20393185311326"></a>
<table><thead align="left"><tr id="row19392653123215"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p6392105315326"><a name="p6392105315326"></a><a name="p6392105315326"></a><strong id="b13706541173716"><a name="b13706541173716"></a><a name="b13706541173716"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p53920531329"><a name="p53920531329"></a><a name="p53920531329"></a><strong id="b15128194510378"><a name="b15128194510378"></a><a name="b15128194510378"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row103921553103211"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1539220536326"><a name="p1539220536326"></a><a name="p1539220536326"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p6392553203217"><a name="p6392553203217"></a><a name="p6392553203217"></a>UART device handle.</p>
</td>
</tr>
<tr id="row1539211532322"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p93921053123210"><a name="p93921053123210"></a><a name="p93921053123210"></a>baudRate</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p93926536328"><a name="p93926536328"></a><a name="p93926536328"></a>Pointer to the UART baud rate.</p>
</td>
</tr>
<tr id="row1239318531326"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17392653123213"><a name="p17392653123213"></a><a name="p17392653123213"></a><strong id="b55191048113716"><a name="b55191048113716"></a><a name="b55191048113716"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1339365316327"><a name="p1339365316327"></a><a name="p1339365316327"></a><strong id="b193671249193713"><a name="b193671249193713"></a><a name="b193671249193713"></a>Description</strong></p>
</td>
</tr>
<tr id="row143939531328"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p2393953153213"><a name="p2393953153213"></a><a name="p2393953153213"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p8393165383218"><a name="p8393165383218"></a><a name="p8393165383218"></a>Succeeded in obtaining the UART baud rate.</p>
</td>
</tr>
<tr id="row5393105363210"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17393125363215"><a name="p17393125363215"></a><a name="p17393125363215"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1539325393211"><a name="p1539325393211"></a><a name="p1539325393211"></a>Failed to obtain the UART baud rate.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to obtain the UART baud rate:
### Obtaining the UART Baud Rate
Call **UartGetBaud()** to obtain the UART baud rate.
```
int32_t UartGetBaud(DevHandle handle, uint32_t *baudRate);
```
**Table 4** Description of UartGetBaud
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| baudRate | Pointer to the UART baud rate obtained.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Example: Obtain the UART baud rate.
```
int32_t ret;
uint32_t baudRate;
......@@ -267,168 +153,102 @@ if (ret != 0) {
}
```
### Setting the UART Device Attributes<a name="section129141884588"></a>
Before performing UART communication, set the UART device attributes by calling the following function:
int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\);
**Table 5** Description of UartSetAttribute
<a name="table1453119335341"></a>
<table><thead align="left"><tr id="row3530433103416"><th class="cellrowborder" valign="top" width="49.980000000000004%" id="mcps1.2.3.1.1"><p id="p1853073310341"><a name="p1853073310341"></a><a name="p1853073310341"></a><strong id="b8706441133719"><a name="b8706441133719"></a><a name="b8706441133719"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50.019999999999996%" id="mcps1.2.3.1.2"><p id="p553083393417"><a name="p553083393417"></a><a name="p553083393417"></a><strong id="b16129154519371"><a name="b16129154519371"></a><a name="b16129154519371"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row55303331347"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1530113313341"><a name="p1530113313341"></a><a name="p1530113313341"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p3530173313346"><a name="p3530173313346"></a><a name="p3530173313346"></a>UART device handle.</p>
</td>
</tr>
<tr id="row45309337342"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p553083319348"><a name="p553083319348"></a><a name="p553083319348"></a>attribute</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p5530133314343"><a name="p5530133314343"></a><a name="p5530133314343"></a>Pointer to the UART device attributes to set.</p>
</td>
</tr>
<tr id="row12530833103415"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p185309331345"><a name="p185309331345"></a><a name="p185309331345"></a><strong id="b18520248203717"><a name="b18520248203717"></a><a name="b18520248203717"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p145309332344"><a name="p145309332344"></a><a name="p145309332344"></a><strong id="b5367174913370"><a name="b5367174913370"></a><a name="b5367174913370"></a>Description</strong></p>
</td>
</tr>
<tr id="row14530203310348"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1653014339343"><a name="p1653014339343"></a><a name="p1653014339343"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1453023323419"><a name="p1453023323419"></a><a name="p1453023323419"></a>Succeeded in setting the UART device attributes.</p>
</td>
</tr>
<tr id="row6531163373412"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p16530123310345"><a name="p16530123310345"></a><a name="p16530123310345"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1953118334347"><a name="p1953118334347"></a><a name="p1953118334347"></a>Failed to set the UART device attributes.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to set the UART device attributes:
### Setting UART Device Attributes
Call **UartSetAttribute()** to set UART device attributes.
```
int32_t UartSetAttribute(DevHandle handle, struct UartAttribute *attribute);
```
**Table 5** Description of UartSetAttribute
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| attribute | Pointer to the UART device attributes to set.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Example: Set UART device attributes.
```
int32_t ret;
struct UartAttribute attribute;
attribute.dataBits = UART_ATTR_DATABIT_7; /* Set the number of data bits to 7. */
attribute.parity = UART_ATTR_PARITY_NONE; /* Set the parity bit to no parity. */
attribute.dataBits = UART_ATTR_DATABIT_7; /* Enable 7 bits to be transferred each time. */
attribute.parity = UART_ATTR_PARITY_NONE; /* Disable parity check. */
attribute.stopBits = UART_ATTR_STOPBIT_1; /* Set the stop bit to 1. */
attribute.rts = UART_ATTR_RTS_DIS; /* Disable the RTS signal. */
attribute.cts = UART_ATTR_CTS_DIS; /* Disable the CTS signal. */
attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* Enable RX FIFO. */
attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* Enable TX FIFO. */
/* Set the UART device attributes. */
/* Set UART device attributes. */
ret = UartSetAttribute(handle, &attribute);
if (ret != 0) {
HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret);
}
```
### Obtaining UART Device Attributes<a name="section18689637165812"></a>
After setting the UART device attributes, obtain the current device attributes by calling the following function:
int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\);
**Table 6** Description of UartGetAttribute
<a name="table17532123316342"></a>
<table><thead align="left"><tr id="row18531193383420"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p85311833143420"><a name="p85311833143420"></a><a name="p85311833143420"></a><strong id="b1770784123715"><a name="b1770784123715"></a><a name="b1770784123715"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p17531103319348"><a name="p17531103319348"></a><a name="p17531103319348"></a><strong id="b0130114519373"><a name="b0130114519373"></a><a name="b0130114519373"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row35311533153413"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p453133333418"><a name="p453133333418"></a><a name="p453133333418"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p753193323420"><a name="p753193323420"></a><a name="p753193323420"></a>UART device handle.</p>
</td>
</tr>
<tr id="row1953103315344"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p35315333346"><a name="p35315333346"></a><a name="p35315333346"></a>attribute</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14531633133416"><a name="p14531633133416"></a><a name="p14531633133416"></a>Pointer to the UART device attributes.</p>
</td>
</tr>
<tr id="row45321433143415"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p653273363417"><a name="p653273363417"></a><a name="p653273363417"></a><strong id="b15211548193719"><a name="b15211548193719"></a><a name="b15211548193719"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1653203312347"><a name="p1653203312347"></a><a name="p1653203312347"></a><strong id="b836815498379"><a name="b836815498379"></a><a name="b836815498379"></a>Description</strong></p>
</td>
</tr>
<tr id="row175320339342"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p10532163383412"><a name="p10532163383412"></a><a name="p10532163383412"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p5532143319341"><a name="p5532143319341"></a><a name="p5532143319341"></a>Succeeded in obtaining the UART device attributes.</p>
</td>
</tr>
<tr id="row125327337340"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19532153317345"><a name="p19532153317345"></a><a name="p19532153317345"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p175321933163410"><a name="p175321933163410"></a><a name="p175321933163410"></a>Failed to obtain the UART device attributes.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to obtain the UART device attributes:
### Obtaining UART Device Attributes
Call **UartGetAttribute()** to obtain the current UART device attributes.
```
int32_t UartGetAttribute(DevHandle handle, struct UartAttribute *attribute);
```
**Table 6** Description of UartGetAttribute
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| attribute | Pointer to the UART device attributes obtained.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Example: Obtain UART device attributes.
```
int32_t ret;
struct UartAttribute attribute;
/* Obtain the UART attributes. */
/* Obtain UART device attributes. */
ret = UartGetAttribute(handle, &attribute);
if (ret != 0) {
HDF_LOGE("UartGetAttribute: failed, ret %d\n", ret);
}
```
### Setting the UART Transmission Mode<a name="section72713435918"></a>
Before performing UART communication, set the UART transmission mode by calling the following function:
int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\);
**Table 7** Description of UartSetTransMode
<a name="table131892266313"></a>
<table><thead align="left"><tr id="row018922615318"><th class="cellrowborder" valign="top" width="49.980000000000004%" id="mcps1.2.3.1.1"><p id="p131891826835"><a name="p131891826835"></a><a name="p131891826835"></a><strong id="b197086411379"><a name="b197086411379"></a><a name="b197086411379"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50.019999999999996%" id="mcps1.2.3.1.2"><p id="p101894269314"><a name="p101894269314"></a><a name="p101894269314"></a><strong id="b813014510375"><a name="b813014510375"></a><a name="b813014510375"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row11893261734"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p81897261333"><a name="p81897261333"></a><a name="p81897261333"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p5190142618310"><a name="p5190142618310"></a><a name="p5190142618310"></a>UART device handle.</p>
</td>
</tr>
<tr id="row1119082615317"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p1519012261314"><a name="p1519012261314"></a><a name="p1519012261314"></a>mode</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p121901026632"><a name="p121901026632"></a><a name="p121901026632"></a>UART transmission mode to set.</p>
</td>
</tr>
<tr id="row19190152612317"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p131900266316"><a name="p131900266316"></a><a name="p131900266316"></a><strong id="b1352194823717"><a name="b1352194823717"></a><a name="b1352194823717"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1519022616315"><a name="p1519022616315"></a><a name="p1519022616315"></a><strong id="b1836924917371"><a name="b1836924917371"></a><a name="b1836924917371"></a>Description</strong></p>
</td>
</tr>
<tr id="row919016261932"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p10190526334"><a name="p10190526334"></a><a name="p10190526334"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p1219012264318"><a name="p1219012264318"></a><a name="p1219012264318"></a>Succeeded in setting the UART transmission mode.</p>
</td>
</tr>
<tr id="row1219017262313"><td class="cellrowborder" valign="top" width="49.980000000000004%" headers="mcps1.2.3.1.1 "><p id="p15190162616316"><a name="p15190162616316"></a><a name="p15190162616316"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50.019999999999996%" headers="mcps1.2.3.1.2 "><p id="p131906262311"><a name="p131906262311"></a><a name="p131906262311"></a>Failed to set the UART transmission mode.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to set the transmission mode to **UART\_MODE\_RD\_BLOCK**:
### Setting the UART Transmission Mode
Call **UartSetTransMode()** to set the UART transmission mode.
```
int32_t UartSetTransMode(DevHandle handle, enum UartTransMode mode);
```
**Table 7** Description of UartSetTransMode
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| mode | UART transmission mode to set.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Example: Set the UART transmission mode to **UART_MODE_RD_BLOCK**.
```
int32_t ret;
/* Set the UART transmission mode. */
......@@ -438,116 +258,64 @@ if (ret != 0) {
}
```
### Writing Data of a Specified Length into a UART Device<a name="section128001736155919"></a>
To write data into a UART device, call the following function:
int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\);
**Table 8** Description of UartWrite
<a name="table27825111368"></a>
<table><thead align="left"><tr id="row1578171123619"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p078112115360"><a name="p078112115360"></a><a name="p078112115360"></a><strong id="b14708841203711"><a name="b14708841203711"></a><a name="b14708841203711"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p37811711163612"><a name="p37811711163612"></a><a name="p37811711163612"></a><strong id="b2131174553712"><a name="b2131174553712"></a><a name="b2131174553712"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row1878291143611"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p07818112360"><a name="p07818112360"></a><a name="p07818112360"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p178281113369"><a name="p178281113369"></a><a name="p178281113369"></a>UART device handle.</p>
</td>
</tr>
<tr id="row7782811123614"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8782911173610"><a name="p8782911173610"></a><a name="p8782911173610"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17782171120366"><a name="p17782171120366"></a><a name="p17782171120366"></a>Pointer to the data to write.</p>
</td>
</tr>
<tr id="row1578251112367"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p3782911183612"><a name="p3782911183612"></a><a name="p3782911183612"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17782161110366"><a name="p17782161110366"></a><a name="p17782161110366"></a>Length of the data to write.</p>
</td>
</tr>
<tr id="row1378281113363"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p87821411183616"><a name="p87821411183616"></a><a name="p87821411183616"></a><strong id="b2052274863718"><a name="b2052274863718"></a><a name="b2052274863718"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p13782111116361"><a name="p13782111116361"></a><a name="p13782111116361"></a><strong id="b73704492377"><a name="b73704492377"></a><a name="b73704492377"></a>Description</strong></p>
</td>
</tr>
<tr id="row47822112365"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p107821011103613"><a name="p107821011103613"></a><a name="p107821011103613"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11782191103610"><a name="p11782191103610"></a><a name="p11782191103610"></a>Succeeded in writing data into the UART device.</p>
</td>
</tr>
<tr id="row11782911113611"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1578221111367"><a name="p1578221111367"></a><a name="p1578221111367"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p9782151110366"><a name="p9782151110366"></a><a name="p9782151110366"></a>Failed to write data into the UART device.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to write data of a specified length into the UART device:
### Writing Data to a UART Device
Call **UartWrite()** to write data of the specified length to a UART device.
```
int32_t UartWrite(DevHandle handle, uint8_t *data, uint32_t size);
```
**Table 8** Description of UartWrite
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| data | Pointer to the data to write.|
| size | Length of the data to write.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative value| The operation failed.|
Example: Write data to a UART device.
```
int32_t ret;
uint8_t wbuff[5] = {1, 2, 3, 4, 5};
/* Write 5-byte data into the UART device. */
/* Write 5-byte data to the UART device. */
ret = UartWrite(handle, wbuff, 5);
if (ret != 0) {
HDF_LOGE("UartWrite: failed, ret %d\n", ret);
}
```
### Reading Data of a Specified Length from a UART Device<a name="section92851601604"></a>
To write data into a UART device, call the following function:
int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\);
**Table 9** Description of UartRead
<a name="table162341717123713"></a>
<table><thead align="left"><tr id="row023313171377"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1123331710376"><a name="p1123331710376"></a><a name="p1123331710376"></a><strong id="b970911411374"><a name="b970911411374"></a><a name="b970911411374"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p523321783715"><a name="p523321783715"></a><a name="p523321783715"></a><strong id="b16132114553713"><a name="b16132114553713"></a><a name="b16132114553713"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row6234417133712"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7233121716379"><a name="p7233121716379"></a><a name="p7233121716379"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17234101753712"><a name="p17234101753712"></a><a name="p17234101753712"></a>UART device handle.</p>
</td>
</tr>
<tr id="row18234151718372"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16234191783711"><a name="p16234191783711"></a><a name="p16234191783711"></a>data</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p923417175378"><a name="p923417175378"></a><a name="p923417175378"></a>Pointer to the buffer for receiving the data.</p>
</td>
</tr>
<tr id="row82341017193711"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13234917103717"><a name="p13234917103717"></a><a name="p13234917103717"></a>size</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p182341817153717"><a name="p182341817153717"></a><a name="p182341817153717"></a>Length of the data to read.</p>
</td>
</tr>
<tr id="row102341617123717"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p172341617163712"><a name="p172341617163712"></a><a name="p172341617163712"></a><strong id="b1352319486376"><a name="b1352319486376"></a><a name="b1352319486376"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1623431763718"><a name="p1623431763718"></a><a name="p1623431763718"></a><strong id="b73711949113718"><a name="b73711949113718"></a><a name="b73711949113718"></a>Description</strong></p>
</td>
</tr>
<tr id="row4234151719372"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p3234131716375"><a name="p3234131716375"></a><a name="p3234131716375"></a>Non-negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p7234171783718"><a name="p7234171783718"></a><a name="p7234171783718"></a>Length of the data read from the UART device.</p>
</td>
</tr>
<tr id="row112340173378"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1423431743714"><a name="p1423431743714"></a><a name="p1423431743714"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p32349178378"><a name="p32349178378"></a><a name="p32349178378"></a>Failed to read data from the UART device.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to read data of a specified length from the UART device:
### Reading Data from a UART Device
Call **UartRead()** to read data of the specified length from a UART device.
```
int32_t UartRead(DevHandle handle, uint8_t *data, uint32_t size);
```
**Table 9** Description of UartRead
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle.|
| data | Pointer to the buffer for receiving the data.|
| size | Length of the data to read.|
| **Return Value**| **Description**|
| Non-negative value| The operation is successful. The length of the data read is returned.|
| Negative value| The operation failed.|
Example: Read data of the specified length from a UART device.
```
int32_t ret;
uint8_t rbuff[5] = {0};
......@@ -558,44 +326,39 @@ if (ret < 0) {
}
```
>![](../public_sys-resources/icon-caution.gif) **CAUTION:**
>Data is successfully read from the UART device if a non-negative value is returned. If the return value is **0**, no valid data can be read from the UART device. If the return value is greater than **0**, the return value is the length of the data actually read from the UART device. The length is less than or equal to the value of **size** and does not exceed the maximum length of data to read at a time specified by the UART controller in use.
> ![icon-caution.gif](../public_sys-resources/icon-caution.gif) **CAUTION**<br/>
> Data is successfully read from the UART device if a non-negative value is returned. If **0** is returned, no valid data can be read from the UART device. A value greater than **0** indicates the length of the data read from the UART device. The data length must be less than or equal to the value of **size** and cannot exceed the maximum length of the data to read at a time specified by the UART controller in use.
### Destroying the UART Device Handle<a name="section1477410521406"></a>
After the UART communication, destroy the UART device handle by calling the following function:
### Closing a UART Device Handle
void UartClose\(DevHandle handle\);
Call **UartClose()** to close a UART device handle.
This function will release the resources previously obtained.
```
void UartClose(DevHandle handle);
```
**Table 10** Description of UartClose
This function releases the resources requested by **UartOpen**.
<a name="table03348317351"></a>
<table><thead align="left"><tr id="row15334837351"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p933411316354"><a name="p933411316354"></a><a name="p933411316354"></a><strong id="b1710184115375"><a name="b1710184115375"></a><a name="b1710184115375"></a>Parameter</strong></p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p16334103143517"><a name="p16334103143517"></a><a name="p16334103143517"></a><strong id="b2013254513370"><a name="b2013254513370"></a><a name="b2013254513370"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row733483103513"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7334530358"><a name="p7334530358"></a><a name="p7334530358"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p133341331356"><a name="p133341331356"></a><a name="p133341331356"></a>UART device handle.</p>
</td>
</tr>
</tbody>
</table>
**Table 10** Description of UartClose
The following example shows how to destroy the UART device handle:
| Parameter| Description|
| -------- | -------- |
| handle | UART device handle to close.|
Example: Close a UART device handle.
```
UartClose(handle); /* Destroy the UART device handle. */
UartClose(handle); /* Close the UART device handle. */
```
## Usage Example<a name="section35404241311"></a>
The following is a usage example of a UART device, including how to obtain the UART device handle, set the baud rate, device attributes, and transmission mode, read data from or write data into the UART device, and then destroy the UART device handle.
## Example
The following example shows how to open a UART device handle, set the baud rate, device attributes, and transmission mode, read data from or write data into the UART device, and then close the UART device handle.
```
#include "hdf_log.h"
#include "uart_if.h"
......@@ -608,16 +371,16 @@ void UartTestSample(void)
uint8_t wbuff[5] = { 1, 2, 3, 4, 5 };
uint8_t rbuff[5] = { 0 };
struct UartAttribute attribute;
attribute.dataBits = UART_ATTR_DATABIT_7; /* Set the number of data bits to 7. */
attribute.parity = UART_ATTR_PARITY_NONE; /* Set the parity bit to no parity. */
attribute.dataBits = UART_ATTR_DATABIT_7; /* Enable 7 bits to be transferred each time. */
attribute.parity = UART_ATTR_PARITY_NONE; /* Disable parity check. */
attribute.stopBits = UART_ATTR_STOPBIT_1; /* Set the stop bit to 1. */
attribute.rts = UART_ATTR_RTS_DIS; /* Disable the RTS signal. */
attribute.cts = UART_ATTR_CTS_DIS; /* Disable the CTS signal. */
attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* Enable RX FIFO. */
attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* Enable TX FIFO. */
/* Set the UART port number actually used. */
/* Enter the UART port number. */
port = 1;
/* Obtain the UART device handle. */
/* Open the UART device handle based on the port number. */
handle = UartOpen(port);
if (handle == NULL) {
HDF_LOGE("UartOpen: failed!\n");
......@@ -629,7 +392,7 @@ void UartTestSample(void)
HDF_LOGE("UartSetBaud: failed, ret %d\n", ret);
goto _ERR;
}
/* Set the UART device attributes. */
/* Set UART device attributes. */
ret = UartSetAttribute(handle, &attribute);
if (ret != 0) {
HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret);
......@@ -641,7 +404,7 @@ void UartTestSample(void)
HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret);
goto _ERR;
}
/* Write 5-byte data into the UART device. */
/* Write 5-byte data to the UART device. */
ret = UartWrite(handle, wbuff, 5);
if (ret != 0) {
HDF_LOGE("UartWrite: failed, ret %d\n", ret);
......@@ -654,7 +417,7 @@ void UartTestSample(void)
goto _ERR;
}
_ERR:
/* Destroy the UART device handle. */
/* Close the UART device handle. */
UartClose(handle);
}
```
\ No newline at end of file
```
......@@ -14,7 +14,7 @@ In the Hardware Driver Foundation (HDF), the Universal Asynchronous Receiver/Tra
**UartHostMethod**:
```
struct UartHostMethod {
int32_t (*Init)(struct UartHost *host);
......@@ -32,18 +32,18 @@ struct UartHostMethod {
**Table 1** Description of the callback functions in UartHostMethod
| Function| Input Parameter| Output Parameter| Return Value| Description|
| Function| Input Parameter| Output Parameter| Return Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| Init | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Initializes a UART device.|
| Deinit | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Deinitializes a UART device.|
| Read | **host**: structure pointer to the UART controller at the core layer.<br>**size**: data size, which is of the uint32_t type.| **data**: pointer to the output data. The value is of the uint8_t type.| HDF_STATUS| Reads data.|
| Write | **host**: structure pointer to the UART controller at the core layer.<br>**data**: pointer to the input data. The value is of the uint8_t type.<br>**size**: data size, which is of the uint32_t type.| –| HDF_STATUS| Writes data.|
| SetBaud | **host**: structure pointer to the UART controller at the core layer.<br>**baudRate**: pointer to the input baud rate. The value is of the uint32_t type. | –| HDF_STATUS| Sets the baud rate.|
| GetBaud | **host**: structure pointer to the UART controller at the core layer.| **baudRate**: pointer to the output baud rate. The value is of the uint32_t type.| HDF_STATUS| Obtains the current baud rate.|
| GetAttribute | **host**: structure pointer to the UART controller at the core layer.| **attribute**: structure pointer to the UART attributes. For details, see **UartAttribute** in **uart_if.h**.| HDF_STATUS| Obtains UART attributes.|
| SetAttribute | **host**: structure pointer to the UART controller at the core layer.<br>**attribute**: structure pointer to the UART attributes to set.| –| HDF_STATUS| Sets UART attributes.|
| SetTransMode | **host**: structure pointer to the UART controller at the core layer.<br>**mode**: transfer mode to set. For details, see **UartTransMode** in **uart_if.h**.| –| HDF_STATUS| Sets the UART transfer mode.|
| PollEvent | **host**: structure pointer to the UART controller at the core layer.<br>**filep**: void pointer to a file.<br>**table**: void pointer to poll_table.| –| HDF_STATUS| Polls for pending events.|
| Init | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Initializes a UART device.|
| Deinit | **host**: structure pointer to the UART controller at the core layer.| –| HDF_STATUS| Deinitializes a UART device.|
| Read | **host**: structure pointer to the UART controller at the core layer.<br>**size**: data size, which is of the uint32_t type.| **data**: pointer to the data read. The value is of the uint8_t type. | HDF_STATUS| Reads data.|
| Write | **host**: structure pointer to the UART controller at the core layer.<br>**data**: pointer to the data to write. The value is of the uint8_t type.<br>**size**: data size, which is of the uint32_t type. | –| HDF_STATUS| Writes data.|
| SetBaud | **host**: structure pointer to the UART controller at the core layer.<br>**baudRate**: pointer to the baud rate to set. The value is of the uint32_t type. | –| HDF_STATUS| Sets the baud rate.|
| GetBaud | **host**: structure pointer to the UART controller at the core layer.| **baudRate**: pointer to the baud rate obtained. The value is of the uint32_t type. | HDF_STATUS| Obtains the current baud rate.|
| GetAttribute | **host**: structure pointer to the UART controller at the core layer.| **attribute**: structure pointer to the attribute obtained. For details, see **UartAttribute** in **uart_if.h**. | HDF_STATUS| Obtains UART attributes.|
| SetAttribute | **host**: structure pointer to the UART controller at the core layer.<br>**attribute**: structure pointer to the attribute to set. | –| HDF_STATUS| Sets UART attributes.|
| SetTransMode | **host**: structure pointer to the UART controller at the core layer.<br>**mode**: transfer mode to set. For details, see **UartTransMode** in **uart_if.h**.| –| HDF_STATUS| Sets the UART transfer mode.|
| PollEvent | **host**: structure pointer to the UART controller at the core layer.<br>**filep**: void pointer to a file.<br>**table**: void pointer to poll_table.| –| HDF_STATUS| Polls for pending events.|
## How to Develop
......@@ -64,7 +64,8 @@ The UART module adaptation involves the following steps:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br>
> For details about the functions in **UartHostMethod**, 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 UART status control and response to interrupts.
......@@ -72,11 +73,16 @@ The UART module adaptation involves the following steps:
The following uses **uart_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.
UART driver entry example:
UART driver entry example:
```
struct HdfDriverEntry g_hdfUartDevice = {
.moduleVersion = 1,
......@@ -89,11 +95,15 @@ The following uses **uart_hi35xx.c** as an example to present the information re
HDF_INIT(g_hdfUartDevice);
```
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **uart_config.hcs** file.<br> 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 **UartHost** members at the core layer.
In this example, there is only one UART controller. If there are multiple UART controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **uart_config** file for each controller.
- **device_info.hcs** configuration example
2. Add the **deviceNode** information to the **device_info.hcs** file and configure the device attributes in the **uart_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 **UartHost** members at the core layer.
In this example, there is only one UART controller. If there are multiple UART controllers, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **uart_config** file for each controller.
- **device_info.hcs** configuration example:
```
root {
device_info {
......@@ -103,11 +113,11 @@ The following uses **uart_hi35xx.c** as an example to present the information re
priority = 50;
device_uart :: device {
device0 :: deviceNode {
policy = 1; // The driver publishes services only for kernel-mode processes.
priority = 40; // Driver startup priority.
permission = 0644; // Permission for the driver to create a device node.
moduleName = "HDF_PLATFORM_UART"; // Driver name, which must be the same as moduleName in the HdfDriverEntry structure.
serviceName = "HDF_PLATFORM_UART_0";// Unique name of the service published by the driver. The name is in the HDF_PLATFORM_UART_X format. X indicates the UART controller number.
policy = 1; // The driver publishes services only for kernel-mode processes.
priority = 40; // Driver startup priority.
permission = 0644; // Permission for the driver to create a device node.
moduleName = "HDF_PLATFORM_UART"; // Driver name, which must be the same as moduleName in the HdfDriverEntry structure.
serviceName = "HDF_PLATFORM_UART_0"; // Unique name of the service published by the driver. The name is in the HDF_PLATFORM_UART_X format. X indicates the UART controller number.
deviceMatchAttr = "hisilicon_hi35xx_uart_0"; // Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
}
device1 :: deviceNode {
......@@ -127,20 +137,20 @@ The following uses **uart_hi35xx.c** as an example to present the information re
- **uart_config.hcs** configuration example
```
root {
platform {
template uart_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
template uart_controller { // Template configuration. In the template, you can configure the common parameters shared by device nodes.
match_attr = "";
num = 0; // (Mandatory) Device number
baudrate = 115200; // (Mandatory) Baud rate. Set the value based on service requirements.
fifoRxEn = 1; // (Mandatory) Enable FIFOs to be received.
fifoTxEn = 1; // (Mandatory) Enable FIFOs to be transferred.
flags = 4; // (Mandatory) Flag signal.
regPbase = 0x120a0000; // (Mandatory) Used for address mapping.
interrupt = 38; // (Mandatory) Interrupt number.
iomemCount = 0x48; // (Mandatory) Used for address mapping.
num = 0; // (Mandatory) Device number.
baudrate = 115200; // (Mandatory) Baud rate. Set the value based on service requirements.
fifoRxEn = 1; // (Mandatory) Enable FIFOs to be received.
fifoTxEn = 1; // (Mandatory) Enable FIFOs to be transferred.
flags = 4; // (Mandatory) Flag signal.
regPbase = 0x120a0000; // (Mandatory) Used for address mapping.
interrupt = 38; // (Mandatory) Interrupt number.
iomemCount = 0x48; // (Mandatory) Used for address mapping.
}
controller_0x120a0000 :: uart_controller {
match_attr = "hisilicon_hi35xx_uart_0";// (Mandatory) The value must be the same as that of deviceMatchAttr of the corresponding device in device_info.hcs.
......@@ -159,43 +169,44 @@ The following uses **uart_hi35xx.c** as an example to present the information re
```
3. Initialize the **UartHost** 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 **UartHostMethod** in **UartHost** (so that the underlying driver functions can be called).
- 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 **uart_config.hcs** file to initialize the members in the custom structure and passes important parameters, such as the device number, to the **UartHost** object at the core layer.
```
struct UartPl011Port { // Interface structure
struct UartPl011Port { // Interface structure
int32_t enable;
unsigned long physBase; // Physical address
unsigned long physBase; // Physical address
uint32_t irqNum; // Interrupt number
uint32_t defaultBaudrate;// Default baud rate
uint32_t flags; // Flags related to the following three macros.
uint32_t defaultBaudrate; // Default baud rate
uint32_t flags; // Flags related to the following three macros
#define PL011_FLG_IRQ_REQUESTED (1 << 0)
#define PL011_FLG_DMA_RX_REQUESTED (1 << 1)
#define PL011_FLG_DMA_TX_REQUESTED (1 << 2)
struct UartDmaTransfer *rxUdt; // DMA transfer
struct UartDriverData *udd; // The data structure is defined as follows:
struct UartDmaTransfer *rxUdt; // DMA transfer
struct UartDriverData *udd; // The data structure is defined as follows:
};
struct UartDriverData { // Structure related to data transfer
struct UartDriverData { // Structure related to data transfer
uint32_t num;
uint32_t baudrate; // Baud rate (configurable)
struct UartAttribute attr; // Attributes, such as the data bit and stop bit, related to data transfer
struct UartTransfer *rxTransfer; // Buffer (FIFO structure)
wait_queue_head_t wait; // Queuing signal related to conditional variables
int32_t count; // Data count
int32_t state; // UART controller state
uint32_t baudrate; // Baud rate (configurable)
struct UartAttribute attr; // Attributes, such as the data bit and stop bit, related to data transfer.
struct UartTransfer *rxTransfer; // Buffer (FIFO structure)
wait_queue_head_t wait; // Queuing signal related to conditional variables
int32_t count; // Data count
int32_t state; // UART controller state
#define UART_STATE_NOT_OPENED 0
#define UART_STATE_OPENING 1
#define UART_STATE_USEABLE 2
#define UART_STATE_SUSPENDED 3
uint32_t flags; // Status flags
uint32_t flags; // Status flags
#define UART_FLG_DMA_RX (1 << 0)
#define UART_FLG_DMA_TX (1 << 1)
#define UART_FLG_RD_BLOCK (1 << 2)
RecvNotify recv; // Pointer to the function that receives serial port data
struct UartOps *ops; // Custom function pointer structure. For details, see device/hisilicon/drivers/uart/uart_pl011.c.
void *private; // It stores the pointer to the start address of UartPl011Port for easy invocation.
RecvNotify recv; // Pointer to the function that receives serial port data.
struct UartOps *ops; // Custom function pointer structure. For details, see device/hisilicon/drivers/uart/uart_pl011.c.
void *private; // It stores the pointer to the start address of UartPl011Port for easy invocation.
};
// UartHost is the controller structure at the core layer. The Init function assigns values to the members of UartHost.
......@@ -205,12 +216,13 @@ The following uses **uart_hi35xx.c** as an example to present the information re
uint32_t num;
OsalAtomic atom;
void *priv; // It stores the pointer to the start address of the vendor's custom structure for easy invocation.
struct UartHostMethod *method; // Hook at the core layer. You need to implement and instantiate its member functions.
struct UartHostMethod *method; // Hook at the core layer. You need to implement and instantiate its member functions.
};
```
- Instantiating **UartHostMethod** in **UartHost** (other members are initialized by **Bind**)
```
// Example in uart_hi35xx.c: instantiate the hook.
struct UartHostMethod g_uartHostMethod = {
......@@ -229,30 +241,30 @@ The following uses **uart_hi35xx.c** as an example to present the information re
- **Bind** function
Input parameter:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
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.
**Table 2** HDF_STATUS
**Table 2** Description of HDF_STATUS
| Status| Description|
| Status| Description|
| -------- | -------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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.|
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| 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:
**Function description**:
Initializes the custom structure object and **UartHost**.
```
//uart_hi35xx.c
static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device)
......@@ -267,10 +279,10 @@ The following uses **uart_hi35xx.c** as an example to present the information re
...
host = (struct UartHost *)OsalMemCalloc(sizeof(*host));// Allocate memory.
...
host->device = device; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost
device->service = &(host->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost
host->device->service->Dispatch = UartIoDispatch;// Assign values to Dispatch of service.
OsalAtomicSet(&host->atom, 0); // Initialize or set the atomic services.
host->device = device; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost.
device->service = &(host->service; // (Mandatory) Prerequisites for conversion between HdfDeviceObject and UartHost.
host->device->service->Dispatch = UartIoDispatch; // Assign values to Dispatch of service.
OsalAtomicSet(&host->atom, 0); // Initialize or set the atomic services.
host->priv = NULL;
host->method = NULL;
return host;
......@@ -279,19 +291,19 @@ The following uses **uart_hi35xx.c** as an example to present the information re
- **Init** function
Input parameter:
**Input parameter**:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
**Return value**:
HDF_STATUS
**HDF_STATUS**
Function description:
**Function description**:
Initializes the custom structure object and **UartHost**, calls the **artAddDev** function at the core layer, and connects to the VFS.
```
int32_t HdfUartDeviceInit(struct HdfDeviceObject *device)
{
......@@ -303,7 +315,7 @@ The following uses **uart_hi35xx.c** as an example to present the information re
...
ret = Hi35xxAttach(host, device); // Initialize the UartHost object.
...
host->method = &g_uartHostMethod; // Hook the UartHostMethod instance.
host->method = &g_uartHostMethod; // Attach the UartHostMethod instance.
return ret;
}
// Initialize UartHost.
......@@ -351,30 +363,34 @@ The following uses **uart_hi35xx.c** as an example to present the information re
```
- **Release** function
Input parameter:
**Input parameter**:
**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 the memory and deletes the controller. This function assigns values to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations.
Releases the memory and deletes the controller. This function assigns values to the **Release** API in the driver entry structure. When the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
>
> All forced conversion operations for obtaining the corresponding object can be successful only when **Init()** has the corresponding value assignment operations.
```
void HdfUartDeviceRelease(struct HdfDeviceObject *device)
{
struct UartHost *host = NULL;
...
host = UartHostFromDevice(device);// Forcibly convert HdfDeviceObject to UartHost by using service. For details about the value assignment, see the Bind function.
host = UartHostFromDevice(device); // Forcibly convert HdfDeviceObject to UartHost by using service. For details about the value assignment, see the Bind function.
...
if (host->priv != NULL) {
Hi35xxDetach(host); // Customized memory release function.
Hi35xxDetach(host); // Customized memory release function.
}
UartHostDestroy(host); // Call the function of the core layer to release the host.
UartHostDestroy(host); // Call the function of the core layer to release the host.
}
static void Hi35xxDetach(struct UartHost *host)
......@@ -382,10 +398,10 @@ The following uses **uart_hi35xx.c** as an example to present the information re
struct UartDriverData *udd = NULL;
struct UartPl011Port *port = NULL;
...
udd = host->priv; // Convert UartHost to UartDriverData.
udd = host->priv; // The conversion from UartHost to UartDriverData is involved.
...
UartRemoveDev(host);// Remove the VFS.
port = udd->private;// Convert UartDriverData to UartPl011Port.
UartRemoveDev (host); // Remove the VFS.
port = udd->private; // The conversion from UartDriverData to UartPl011Port is involved.
if (port != NULL) {
if (port->physBase != 0) {
OsalIoUnmap((void *)port->physBase);// Unmap addresses.
......@@ -393,7 +409,7 @@ The following uses **uart_hi35xx.c** as an example to present the information re
OsalMemFree(port);
udd->private = NULL;
}
OsalMemFree(udd);//Release UartDriverData.
OsalMemFree (udd); // Release UartDriverData.
host->priv = NULL;
}
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册