The analog-to-digital converter \(ADC\) is a device that converts analog signals into digital signals. In the Hardware Driver Foundation \(HDF\), the ADC module uses the unified service mode for API adaptation. In this mode, a device service is used as the ADC manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the ADC has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services.
## Overview
**Figure 1** Unified service mode<aname="fig14423182615525"></a>
An analog-to-digital converter (ADC) is a device that converts analog signals into digital signals. In the Hardware Driver Foundation (HDF), the ADC module uses the unified service mode for API adaptation. In this mode, a device service is used as the ADC manager to handle external access requests in a unified manner, which is reflected in the configuration file. The unified service mode applies to the scenario where there are many device objects of the same type, for example, when the ADC has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services.
| read | **device**: structure pointer to the ADC controller at the core layer.<br>**channel**: channel ID, which is of the uint32_t type.| **val**: pointer to the signal data to be transmitted. It is of the uint32_t type.| HDF_STATUS| Reads the signal data sampled by the ADC.|
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p474720389561"><aname="p474720389561"></a><aname="p474720389561"></a><strongid="b167472038115611"><aname="b167472038115611"></a><aname="b167472038115611"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p>
<pid="p14459238536"><aname="p14459238536"></a><aname="p14459238536"></a><strongid="b179891252205514"><aname="b179891252205514"></a><aname="b179891252205514"></a>channel</strong>: channel ID of the uint32_t type.</p>
</td>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.3 "><pid="p746423195320"><aname="p746423195320"></a><aname="p746423195320"></a><strongid="b626111125816"><aname="b626111125816"></a><aname="b626111125816"></a>val</strong>: pointer to the signal data to be transmitted. It is of the uint32_t type.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="p146152311537"><aname="p146152311537"></a><aname="p146152311537"></a>Reads the signal data sampled by the ADC.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p1446112318536"><aname="p1446112318536"></a><aname="p1446112318536"></a><strongid="b345886135912"><aname="b345886135912"></a><aname="b345886135912"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="p1346223185318"><aname="p1346223185318"></a><aname="p1346223185318"></a>Stops the ADC device.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.2 "><pid="p17461323185314"><aname="p17461323185314"></a><aname="p17461323185314"></a><strongid="b1988212105110"><aname="b1988212105110"></a><aname="b1988212105110"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p>
<tdclass="cellrowborder"valign="top"width="20%"headers="mcps1.2.6.1.5 "><pid="p1471623195311"><aname="p1471623195311"></a><aname="p1471623195311"></a>Starts the ADC device.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section100579767165048"></a>
The ADC module adaptation involves the following steps:
The ADC module adaptation involves the following steps:
1. Instantiate the driver entry.
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- Add the **deviceNode** information to the **device_info.hcs** file.
-\(Optional\) Add the **adc\_config.hcs** file.
- (Optional) Add the **adc_config.hcs** file.
3. Instantiate the ADC controller object.
3. Instantiate the ADC controller object.
- Initialize **AdcDevice**.
- Initialize **AdcDevice**.
- Instantiate **AdcMethod** in the **AdcDevice** object.
- Instantiate **AdcMethod** in the **AdcDevice** object.
> For details about the functions in **AdcMethod**, see [Available APIs](#available-apis).
For details, 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 check whether signals are successfully collected.
4.\(Optional\) Debug the driver.
For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the signal collection is successful.
## Development Example<a name="section1745221471165048"></a>
## Development Example
The following uses **adc\_hi35xx.c** as an example to present the contents that need to be provided by the vendor to implement device functions.
The following uses **adc_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.
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.
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.
ADC driver entry example:
Generally, HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, HDF calls **Release** to release driver resources and exits.
Many devices may connect to the ADC. In the HDF, a manager object needs to be created for the ADC. When a device needs to be started, the manager object locates the target device based on the specified parameters.
- ADC driver entry reference
The driver of the ADC manager is implemented by the core layer. The **Init** function of the driver layer calls **AdcDeviceAdd** of the core layer to add devices to the ADC manager. Therefore, vendors do not need to implement this part.
Many devices may connect to the ADC. In the HDF, a manager object needs to be created for the ADC. When a device needs to be started, the manager object locates the device based on the specified parameters.
The driver of the ADC manager is implemented by the core layer. Vendors do not need to pay attention to the implementation of this part. However, when they implement the **Init** function, the **AdcDeviceAdd** function of the core layer must be called to implement the corresponding features.
@@ -121,48 +81,24 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -121,48 +81,24 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
.moduleVersion = 1,
.moduleVersion = 1,
.Init = AdcManagerInit,
.Init = AdcManagerInit,
.Release = AdcManagerRelease,
.Release = AdcManagerRelease,
.moduleName = "HDF_PLATFORM_ADC_MANAGER",// This parameter corresponds to device0 in the device_info file.
.moduleName = "HDF_PLATFORM_ADC_MANAGER",// Correspond to device0 in the device_info file.
};
};
HDF_INIT(g_adcManagerEntry);
HDF_INIT(g_adcManagerEntry);
```
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **adc\_config.hcs** file. The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or value ranges of the **AdcDevice** members at the core layer.
2. Add **deviceNode** to the **device_info.hcs** file, and configure the device attributes in the **adc_config.hcs** file.<br> The **deviceNode** information is related to registration of the driver entry. The device attribute values are closely related to the driver implementation and the default values or restriction ranges of the **AdcDevice** members at the core layer.
In the unified service mode, the first device node in the **device_info** file must be the ADC manager. The parameters must be set as follows:
In the unified service mode, the first device node in the **device\_info** file must be the ADC manager, and the parameters must be set as follows:
Configure ADC controller information from the second node. This node specifies a type of ADC controllers rather than an ADC controller. In this example, there is only one ADC device. If there are multiple ADC devices, add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **adc_config** file for each device.
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry912596825165048p0"><a name="entry912596825165048p0"></a><a name="entry912596825165048p0"></a>It has a fixed value of <strong id="b581184091716"><a name="b581184091716"></a><a name="b581184091716"></a>HDF_PLATFORM_ADC_MANAGER</strong>.</p>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry781016408165048p0"><a name="entry781016408165048p0"></a><a name="entry781016408165048p0"></a>The value is <strong id="b229121291813"><a name="b229121291813"></a><a name="b229121291813"></a>0</strong>, which indicates that no service is published.</p>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry367170471165048p0"><a name="entry367170471165048p0"></a><a name="entry367170471165048p0"></a>This parameter is not used.</p>
</td>
</tr>
</tbody>
</table>
Configure ADC controller information from the second node. This node specifies a type of ADC controllers rather than an ADC controller. In this example, there is only one ADC device. If there are multiple ADC devices, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **adc\_config** file.
- **device\_info.hcs** configuration reference
```
```
root {
root {
...
@@ -177,20 +113,20 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -177,20 +113,20 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
serviceName = "HDF_PLATFORM_ADC_MANAGER";
serviceName = "HDF_PLATFORM_ADC_MANAGER";
}
}
device1 :: deviceNode {
device1 :: deviceNode {
policy = 0; // The value 0 indicates that no service needs to be published.
policy = 0; // The value 0 indicates that no service is published.
priority = 55; // Driver startup priority
priority = 55; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver
permission = 0644; // Permission to create device nodes for the driver.
moduleName = "hi35xx_adc_driver"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
moduleName = "hi35xx_adc_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "HI35XX_ADC_DRIVER"; // (Mandatory) Unique name of the service published by the driver
serviceName = "HI35XX_ADC_DRIVER"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hisilicon_hi35xx_adc";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller in adc_config.hcs.
deviceMatchAttr = "hisilicon_hi35xx_adc";// (Mandatory) Private data of the controller. The value must be the same as that of the corresponding controller in adc_config.hcs.
} // The specific controller information is in adc_config.hcs.
} // The specific controller information is configured in adc_config.hcs.
}
}
}
}
}
}
}
}
```
```
-**adc_config.hcs** configuration example
- adc\_config.hcs configuration reference
```
```
root {
root {
...
@@ -198,13 +134,13 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -198,13 +134,13 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
adc_config_hi35xx {
adc_config_hi35xx {
match_attr = "hisilicon_hi35xx_adc";
match_attr = "hisilicon_hi35xx_adc";
template adc_device {
template adc_device {
regBasePhy = 0x120e0000;// Physical base address of the register
regBasePhy = 0x120e0000;// Physical base address of the register.
regSize = 0x34; // Bit width of the register
regSize = 0x34; // Bit width of the register.
deviceNum = 0; // Device number
deviceNum = 0; // Device number.
validChannel = 0x1; // Valid channel
validChannel = 0x1; // Valid channel.
dataWidth = 10; // Data bit width of received signals
dataWidth = 10; // Bit width of the received signal.
scanMode = 1; // Scan mode
scanMode = 1; // Scan mode.
delta = 0; // Delta parameter
delta = 0; // Delta parameter.
deglitch = 0;
deglitch = 0;
glitchSample = 5000;
glitchSample = 5000;
rate = 20000;
rate = 20000;
...
@@ -218,29 +154,30 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -218,29 +154,30 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
}
}
```
```
3. Initialize the **AdcDevice** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **AdcMethod**\(used to call underlying functions of the driver\) in **AdcDevice**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
3. Initialize the **AdcDevice** 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 **AdcMethod** in **AdcDevice** (so that the underlying driver functions can be called).
- Custom structure reference
- Defining a custom structure
To the driver, the custom structure holds parameters and data. The **DeviceResourceIface()** function provided by the HDF reads **adc_config.hcs** to initialize the custom structure and passes some important parameters, such as the device number and bus number, to the **AdcDevice** object at the core layer.
To the driver, the custom structure carries parameters and data. The values in the **adc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number and bus number, are also passed to the **AdcDevice** object at the core layer.
```
```
struct Hi35xxAdcDevice {
struct Hi35xxAdcDevice {
struct AdcDevice device;// (Mandatory) Control object of the core layer. For details, see the description of AdcDevice.
struct AdcDevice device;// (Mandatory) Control object of the core layer. For details, see the description of AdcDevice.
volatile unsigned char *regBase;// (Mandatory) Base address of the register
volatile unsigned char *regBase;// (Mandatory) Base address of the register.
volatile unsigned char *pinCtrlBase;
volatile unsigned char *pinCtrlBase;
uint32_t regBasePhy; // (Mandatory) Physical base address of the register
uint32_t regBasePhy; // (Mandatory) Physical base address of the register.
uint32_t regSize; // (mandatory) Bit width of the register
uint32_t regSize; // (Mandatory) Bit width of the register.
uint32_t deviceNum; // (Mandatory) Device number
uint32_t deviceNum; // (Mandatory) Device number.
uint32_t dataWidth; // (Mandatory) Data bit width of received signals
uint32_t dataWidth; // (Mandatory) Data bit width of received signals.
// AdcDevice is the core layer controller structure. Its members are assigned with values by using the Init function.
// AdcDevice is the core layer controller structure. The **Init()** function assigns values to the members of AdcDevice.
struct AdcDevice {
struct AdcDevice {
const struct AdcMethod *ops;
const struct AdcMethod *ops;
OsalSpinlock spin;
OsalSpinlock spin;
...
@@ -251,7 +188,8 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -251,7 +188,8 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
};
};
```
```
- Instantiate the callback function structure **AdcMethod** in **AdcDevice**. The **AdcLockMethod** callback function structure is not implemented in this example. To instantiate the structure, refer to the I2C driver development. Other members are initialized in the **Init** function.
- Instantiating **AdcMethod** in **AdcDevice**<br>This example does not provide the implementation of the **AdcLockMethod** callback. For details, see I2C driver development. Other members are initialized by the **Init** function.
```
```
static const struct AdcMethod g_method = {
static const struct AdcMethod g_method = {
...
@@ -260,56 +198,24 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -260,56 +198,24 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
.start = Hi35xxAdcStart,
.start = Hi35xxAdcStart,
};
};
```
```
-**Init** function
Input parameter:
- Init function
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Input parameters:
Return value:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
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.
Return values:
| Status| Description|
| -------- | -------- |
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.\)
hi35xx->device.ops = &g_method; // (Mandatory) Mount the AdcMethod instance object.
hi35xx->device.ops = &g_method; // (Mandatory) Attach the AdcMethod instance object.
ret = AdcDeviceAdd(&hi35xx->device); // (Mandatory and important) Call this function to set the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned.
ret = AdcDeviceAdd(&hi35xx->device)); // (Mandatory) Call this function to set the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned.
...
...
return HDF_SUCCESS;
return HDF_SUCCESS;
__ERR__:
__ERR__:
if (hi35xx != NULL) { // If the operation fails, you need to execute the initialization function reversely.
if (hi35xx != NULL) { // If the operation fails, execute the initialization function reversely.
if (hi35xx->regBase != NULL) {
if (hi35xx->regBase != NULL) {
OsalIoUnmap((void *)hi35xx->regBase);
OsalIoUnmap((void *)hi35xx->regBase);
hi35xx->regBase = NULL;
hi35xx->regBase = NULL;
...
@@ -363,20 +269,20 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
...
@@ -363,20 +269,20 @@ The following uses **adc\_hi35xx.c** as an example to present the contents that
return ret;
return ret;
}
}
```
```
-**Release** function
- Release function
Input parameter:
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return value:
Return values:
No value is returned.
–
Function description:
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 **Init** function has the corresponding value assignment operations.
Releases the memory and deletes the controller. This function assigns values to the **Release** function in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the value assignment operations.
A digit-to-analog converter (DAC) is a device that converts a digital signal into an analog signal in electronics.
A digit-to-analog converter (DAC) is a device that converts a digital signal into an analog signal in electronics.
### Basic Concepts<a name="3"></a>
The DAC module supports development of digital-to-analog conversion. The DAC module provides the output channel for the process control computer system. It connects to the executor to implement automatic control of the production process. It is also an important module in the analog-to-digital converter using feedback technologies.
The DAC module supports development of digital-to-analog conversion. The DAC module provides the output channel for the process control computer system. It connects to the executor to implement automatic control of the production process. It is also an important module in the analog-to-digital converter using feedback technologies.
### Basic Concepts
- Resolution
- Resolution
The number of binary bits that can be converted by a DAC. A greater number of bits indicates a higher resolution.
The number of binary bits that can be converted by a DAC. A greater number of bits indicates a higher resolution.
...
@@ -27,41 +26,40 @@ The DAC module supports development of digital-to-analog conversion. The DAC mod
...
@@ -27,41 +26,40 @@ The DAC module supports development of digital-to-analog conversion. The DAC mod
The least significant byte (LSB) refers to bit 0 (the least significant bit) in a binary number.
The least significant byte (LSB) refers to bit 0 (the least significant bit) in a binary number.
### Working Principles<a name="4"></a>
### Working Principles
In the Hardware Driver Foundation (HDF), the DAC module uses the unified service mode for API adaptation. In this mode, a device service is used as the DAC manager to handle access requests from the devices of the same type in a unified manner. The unified service mode applies to the scenario where there are many device objects of the same type. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. The figure below shows the unified service mode.
In the Hardware Driver Foundation (HDF), the DAC module uses the unified service mode for API adaptation. In this mode, a device service is used as the DAC manager to handle access requests from the devices of the same type in a unified manner. The unified service mode applies to the scenario where there are many device objects of the same type. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. The figure below shows the unified service mode.
The DAC module is divided into the following layers:
The DAC module is divided into the following layers:
- The interface layer provides APIs for opening or closing a device and writing data.
- The interface layer provides APIs for opening or closing a device and writing data.
- The core layer provides the capabilities of binding, initializing, and releasing devices.
- The core layer provides the capabilities of binding, initializing, and releasing devices.
- The adaptation layer implements other functions.
- The adaptation layer implements other functions.
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.
>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer.
**Figure 1** Unified service mode<aname="fig14423182615525"></a>
**Figure 1** Unified service mode


### Constraints
### Constraints<a name="5"></a>
Currently, the DAC module supports only the kernels (LiteOS) of mini and small systems.
Currently, the DAC module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines<a name="6"></a>
## Development Guidelines
### When to Use<a name="7"></a>
### When to Use
The DAC module is used for digital-to-analog conversion, audio output, and motor control. The DAC driver is used when the digital signals input by the DAC module are converted into analog signals to output.
The DAC module is used for digital-to-analog conversion, audio output, and motor control. The DAC driver is used when the digital signals input by the DAC module are converted into analog signals to output.
### Available APIs<a name="8"></a>
### Available APIs
The **DacMethod** is used to call the DAC driver functions.
The **DacMethod** is used to call the DAC driver APIs.
**DacMethod** definition:
**DacMethod**:
```
```
struct DacMethod {
struct DacMethod {
...
@@ -76,17 +74,17 @@ struct DacMethod {
...
@@ -76,17 +74,17 @@ struct DacMethod {
**Table 1** Description of the DacMethod structure
**Table 1** Description of the DacMethod structure
| write | **device**: pointer to the DAC controller at the core layer.<br>**channel**: channel ID, which is of the uint32_t type.<br>val: data to write, which is of the uint32_t type.| - | HDF_STATUS| Writes the target digit-to-analog (DA) value.|
| write | **device**: structure pointer to the DAC controller at the core layer.<br>**channel**: channel ID, which is of the uint32_t type.<br>**val**: data to write, which is of the uint32_t type.| - | HDF_STATUS| Writes the target digital-to-analog (DA) value.|
| start | **device**: pointer to the DAC controller at the core layer. | - | HDF_STATUS| Starts a DAC device. |
| start | **device**: structure pointer to the DAC controller at the core layer. | - | HDF_STATUS| Starts a DAC device. |
| stop | **device**: pointer to the DAC controller at the core layer. | - | HDF_STATUS| Stops a device. |
| stop | **device**: structure pointer to the DAC controller at the core layer. | - | HDF_STATUS| Stops a DAC device. |
### How to Develop<a name="9"></a>
### How to Develop
The DAC module adaptation procedure is as follows:
The DAC module adaptation procedure is as follows:
...
@@ -97,7 +95,7 @@ The DAC module adaptation procedure is as follows:
...
@@ -97,7 +95,7 @@ The DAC module adaptation procedure is as follows:
1. Instantiate the driver entry.
1. Instantiate the driver entry.
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 are 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.
...
@@ -122,7 +120,7 @@ The DAC module adaptation procedure is as follows:
...
@@ -122,7 +120,7 @@ The DAC module adaptation procedure is as follows:
| policy | **0**, which indicates that no service is published.|
| policy | **0**, which indicates that no service is published.|
| priority | Driver startup priority. The value range is 0 to 200. A larger value indicates a lower priority. If the priorities are the same, the device loading sequence is not ensured.|
| priority | Driver startup priority. The value range is 0 to 200. A larger value indicates a lower priority. For the drivers with the same priority, the device loads them randomly.|
| permission | Driver permission.|
| permission | Driver permission.|
| moduleName | The value is **HDF_PLATFORM_DAC_MANAGER**.|
| moduleName | The value is **HDF_PLATFORM_DAC_MANAGER**.|
| serviceName | The value is **HDF_PLATFORM_DAC_MANAGER**.|
| serviceName | The value is **HDF_PLATFORM_DAC_MANAGER**.|
...
@@ -130,12 +128,12 @@ The DAC module adaptation procedure is as follows:
...
@@ -130,12 +128,12 @@ The DAC module adaptation procedure is as follows:
Configure DAC controller information from the second node. This node specifies a type of DAC controllers rather than a specific DAC controller. In this example, there is only one DAC device. If there are multiple DAC devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **dac_config** file.
Configure DAC controller information from the second node. This node specifies a type of DAC controllers rather than a specific DAC controller. In this example, there is only one DAC device. If there are multiple DAC devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **dac_config** file.
**device_info.hcs** configuration reference
**device_info.hcs** configuration example
```
```
root {
root {
device_dac :: device {
device_dac :: device {
// device0 is the DAC manager.
// device0 is a DAC manager.
device0 :: deviceNode {
device0 :: deviceNode {
policy = 0;
policy = 0;
priority = 52;
priority = 52;
...
@@ -144,7 +142,7 @@ The DAC module adaptation procedure is as follows:
...
@@ -144,7 +142,7 @@ The DAC module adaptation procedure is as follows:
moduleName = "HDF_PLATFORM_DAC_MANAGER";
moduleName = "HDF_PLATFORM_DAC_MANAGER";
}
}
}
}
// dac_virtual is the DAC controller.
// dac_virtual is a DAC controller.
dac_virtual :: deviceNode {
dac_virtual :: deviceNode {
policy = 0;
policy = 0;
priority = 56;
priority = 56;
...
@@ -178,9 +176,9 @@ The DAC module adaptation procedure is as follows:
...
@@ -178,9 +176,9 @@ The DAC module adaptation procedure is as follows:
}
}
```
```
3. Instantiate the APIs of the core layer.
3. Instantiate the core layer APIs.
- Initialize the **DacDevice** object.
- Initializing the **DacDevice** object
Initialize the **DacDevice** member in the **VirtualDacParseAndInit** function.
Initialize the **DacDevice** member in the **VirtualDacParseAndInit** function.
...
@@ -201,28 +199,28 @@ The DAC module adaptation procedure is as follows:
...
@@ -201,28 +199,28 @@ The DAC module adaptation procedure is as follows:
// Initialize the pointer to the virtual DAC device.
VirtualDacDeviceInit(virtual);
VirtualDacDeviceInit(virtual);
// Initialize the priv object in DacDevice.
// Initialize the priv object in DacDevice.
virtual->device.priv = (void *)node;
virtual->device.priv = (void *)node;
...
@@ -235,9 +233,9 @@ The DAC module adaptation procedure is as follows:
...
@@ -235,9 +233,9 @@ The DAC module adaptation procedure is as follows:
if (ret != HDF_SUCCESS) {
if (ret != HDF_SUCCESS) {
// Failed to add the device.
// Failed to add the device.
HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret);
HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret);
// Release the virtual space.
// Release the space for the virtual DAC device.
OsalMemFree(virtual);
OsalMemFree(virtual);
// Set the virtual pointer to null.
// Set this pointer to null.
virtual = NULL;
virtual = NULL;
return ret;
return ret;
}
}
...
@@ -248,9 +246,9 @@ The DAC module adaptation procedure is as follows:
...
@@ -248,9 +246,9 @@ The DAC module adaptation procedure is as follows:
- Custom structure reference
- Defining a custom structure
The custom structure holds parameters and data for the driver. Define the custom structure based on the function parameters of the device. The HDF reads the values in the **dac_config.hcs** file using the **DacTestReadConfig()** function and initializes the structure members using **DeviceResourceIface()**. Some important values, such as the device number and bus number, are also passed to the **DacDevice** object at the core layer.
The custom structure holds parameters and data for the driver. Define the custom structure based on the function parameters of the device. The **DacTestReadConfig()** provided by the HDF reads the values in the **dac_config.hcs** file, and **DeviceResourceIface()** initializes the custom structure and passes some important parameters, such as the device number and bus number, to the **DacDevice** object at the core layer.
```
```
struct VirtualDacDevice {
struct VirtualDacDevice {
...
@@ -260,7 +258,7 @@ The DAC module adaptation procedure is as follows:
...
@@ -260,7 +258,7 @@ The DAC module adaptation procedure is as follows:
uint32_t rate; // (Mandatory) Sampling rate.
uint32_t rate; // (Mandatory) Sampling rate.
};
};
// DacDevice is the core layer controller structure. Its members are assigned with values in the Init() function.
// DacDevice is the core layer controller structure. The Init() function assigns values to the members of DacDevice.
struct DacDevice {
struct DacDevice {
const struct DacMethod *ops;
const struct DacMethod *ops;
OsalSpinlock spin; // Spinlock.
OsalSpinlock spin; // Spinlock.
...
@@ -271,8 +269,7 @@ The DAC module adaptation procedure is as follows:
...
@@ -271,8 +269,7 @@ The DAC module adaptation procedure is as follows:
};
};
```
```
- Instantiate the **DacDevice** in **DacMethod**.
- Instantiating **DacDevice** in **DacMethod**.
The **VirtualDacWrite**, **VirtualDacStop**, and **VirtualDacStart** functions are instantiated in **dac_virtual.c**.
The **VirtualDacWrite**, **VirtualDacStop**, and **VirtualDacStart** functions are instantiated in **dac_virtual.c**.
...
@@ -290,13 +287,13 @@ The DAC module adaptation procedure is as follows:
...
@@ -290,13 +287,13 @@ The DAC module adaptation procedure is as follows:
- **Init** function
- **Init** function
Input parameters:
Input parameter:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value:
Return value:
HDF_STATUS (The table below lists some status. For details about other status, see HDF_STATUS in the /drivers/framework/include/utils/hdf_base.h file.)
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.
| State | Description |
| State | Description |
| ---------------------- | -------------- |
| ---------------------- | -------------- |
...
@@ -355,7 +352,7 @@ The DAC module adaptation procedure is as follows:
...
@@ -355,7 +352,7 @@ The DAC module adaptation procedure is as follows:
if (virtual != NULL) {
if (virtual != NULL) {
// Release the memory.
// Release the memory.
OsalMemFree(virtual);
OsalMemFree(virtual);
// Set the pointer to null.
// Set this pointer to null.
virtual = NULL;
virtual = NULL;
}
}
...
@@ -391,13 +388,13 @@ The DAC module adaptation procedure is as follows:
...
@@ -391,13 +388,13 @@ The DAC 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 configuration file information.
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value
Return value:
This function returns no value.
No value is returned.
Function description:
Function description:
...
@@ -410,15 +407,15 @@ The DAC module adaptation procedure is as follows:
...
@@ -410,15 +407,15 @@ The DAC module adaptation procedure is as follows:
int32_t ret;
int32_t ret;
// Define the DAC device number.
// Define the DAC device number.
int16_t devNum;
int16_t devNum;
// Pointer of the DacDevice structure.
// Pointer to the DacDevice structure.
struct DacDevice *device = NULL;
struct DacDevice *device = NULL;
// Pointer of the VirtualDacDevice structure.
// Pointer to the VirtualDacDevice structure.
struct VirtualDacDevice *virtual = NULL;
struct VirtualDacDevice *virtual = NULL;
// Pointer of the DeviceResourceIface structure.
// Pointer to the DeviceResourceIface structure.
struct DeviceResourceIface *drsOps = NULL;
struct DeviceResourceIface *drsOps = NULL;
// Obtain device resources through the instance entry.
// Obtain device resources through the instance entry.