提交 84e321b7 编写于 作者: D duangavin123

update 导入OpenHarmony工程

Signed-off-by: Nduangavin123 <duanxichao@huawei.com>
上级 00b6206e
......@@ -153,7 +153,7 @@ In addition, OpenHarmony provides a series of optional system components that ca
</td>
<td class="cellrowborder" valign="top" width="36.053605360536054%" headers="mcps1.2.4.1.2 "><p id="p185185615284"><a name="p185185615284"></a><a name="p185185615284"></a>Porting and adapting the <span id="text1434016533511"><a name="text1434016533511"></a><a name="text1434016533511"></a>OpenHarmony</span> to a third-party library</p>
</td>
<td class="cellrowborder" valign="top" width="36.07360736073608%" headers="mcps1.2.4.1.3 "><a name="ul14724164204819"></a><a name="ul14724164204819"></a><ul id="ul14724164204819"><li><a href="porting/standard-system-porting-guide.md">Standard System SoC Porting Guide</a></li></ul>
<td class="cellrowborder" valign="top" width="36.07360736073608%" headers="mcps1.2.4.1.3 "><a name="ul14724164204819"></a><a name="ul14724164204819"></a><ul id="ul14724164204819"><li><a href="porting/standard-system-porting-guide.md">Standard System SoC Porting Guide</a></li><li><a href="porting/porting-linux-kernel-overview.md">A Method for Rapidly Porting the OpenHarmony Linux Kernel </a></li></ul>
</td>
</tr>
<tr id="row869853125119"><td class="cellrowborder" valign="top" width="27.872787278727873%" headers="mcps1.2.4.1.1 "><p id="p3691530511"><a name="p3691530511"></a><a name="p3691530511"></a>Contributing components</p>
......
......@@ -4,10 +4,22 @@
- [HDF Overview](driver-hdf-overview.md)
- [Driver Development](driver-hdf-development.md)
- [Driver Service Management](driver-hdf-servicemanage.md)
- [Driver Message Mechanism Management](driver-hdf-news.md)
- [Driver Message Mechanism Management](driver-hdf-message-management.md)
- [Driver Configuration Management](driver-hdf-manage.md)
- [HDF Development Example](driver-hdf-sample.md)
- [Platform Drivers](driver-platform.md)
- [Platform Driver Development](driver-develop.md)
- [ADC](driver-platform-adc-develop.md)
- [GPIO](driver-platform-gpio-develop.md)
- [I2C](driver-platform-i2c-develop.md)
- [MIPI-DSI](driver-platform-mipidsi-develop.md)
- [MMC](driver-platform-mmc-develop.md)
- [PWM](driver-platform-pwm-develop.md)
- [RTC](driver-platform-rtc-develop.md)
- [SDIO](driver-platform-sdio-develop.md)
- [SPI](driver-platform-spi-develop.md)
- [UART](driver-platform-uart-develop.md)
- [Watchdog](driver-platform-watchdog-develop.md)
- [Platform Driver Usage](driver-platform.md)
- [GPIO](driver-platform-gpio-des.md)
- [I2C](driver-platform-i2c-des.md)
- [RTC](driver-platform-rtc-des.md)
......@@ -16,7 +28,8 @@
- [UART](driver-platform-uart-des.md)
- [Watchdog](driver-platform-watchdog-des.md)
- [MIPI DSI](driver-platform-mipidsi-des.md)
- [Peripherals](driver-peripherals.md)
- [PWM](driver-platform-pwm-des.md)
- [Peripheral Driver Usage](driver-peripherals.md)
- [LCD](driver-peripherals-lcd-des.md)
- [TOUCHSCREEN](driver-peripherals-touch-des.md)
- [Sensor](driver-peripherals-sensor-des.md)
......
# Platform Driver Development<a name="EN-US_TOPIC_0000001160769576"></a>
- **[ADC](driver-platform-adc-develop.md)**
- **[GPIO](driver-platform-gpio-develop.md)**
- **[I2C](driver-platform-i2c-develop.md)**
- **[MIPI-DSI](driver-platform-mipidsi-develop.md)**
- **[MMC](driver-platform-mmc-develop.md)**
- **[PWM](driver-platform-pwm-develop.md)**
- **[RTC](driver-platform-rtc-develop.md)**
- **[SDIO](driver-platform-sdio-develop.md)**
- **[SPI](driver-platform-spi-develop.md)**
- **[UART](driver-platform-uart-develop.md)**
- **[Watchdog](driver-platform-watchdog-develop.md)**
......@@ -5,12 +5,10 @@
## Introduction<a name="section157425168112"></a>
The HDF is designed based on the component-based driver model. It provides more refined driver management to make driver development and deployment more standard. Device drivers of the same type are placed in the same host. You can develop and deploy the drivers separately. One driver can have multiple nodes. [Figure 1](#fig5487113011526) shows the HDF driver model.
The HDF is designed based on the component-based driver model. It provides more refined driver management to make driver development and deployment more standard. Device drivers of the same type are placed in the same host. You can develop and deploy the drivers separately. One driver can have multiple nodes. [Figure 1](#fig3580184214210) shows the HDF driver model.
**Figure 1** HDF driver model<a name="fig5487113011526"></a>
![](figure/en-us_image_0000001054564784.png)
**Figure 1** HDF driver model<a name="fig3580184214210"></a>
![](figures/hdf-driver-model.png "hdf-driver-model")
## How to Develop<a name="section1969312275533"></a>
......@@ -167,7 +165,7 @@ Driver development based on the HDF consists of two parts: driver implementation
> DEVICE_PRELOAD_INVALID
> } DevicePreload;
> ```
> When the **preload** field in the configuration file is set to **0** \(**DEVICE\_PRELOAD\_ENABLE**\), the driver is loaded by default during system startup. When this field is set to **1** \(**DEVICE\_PRELOAD\_ENABLE\_STEP2**\), the driver is loaded after system startup if quick start is enabled; it is loaded during system startup otherwise. When this field is set to **2** \(**DEVICE\_PRELOAD\_DISABLE**\), the driver is not loaded by default during system startup and can be dynamically loaded later. If the driver service does not exist when a user-level application obtains the driver service \(for details about how to obtain the driver service, see [Driver Message Mechanism Management](driver-hdf-news.md)\), the HDF attempts to dynamically load the driver.
> When the **preload** field in the configuration file is set to **0** \(**DEVICE\_PRELOAD\_ENABLE**\), the driver is loaded by default during system startup. When this field is set to **1** \(**DEVICE\_PRELOAD\_ENABLE\_STEP2**\), the driver is loaded after system startup if quick start is enabled; it is loaded during system startup otherwise. When this field is set to **2** \(**DEVICE\_PRELOAD\_DISABLE**\), the driver is not loaded by default during system startup and can be dynamically loaded later. If the driver service does not exist when a user-level application obtains the driver service \(for details about how to obtain the driver service, see [Driver Message Mechanism Management](driver-hdf-message-management.md)\), the HDF attempts to dynamically load the driver.
>- Sequential loading \(drivers must be loaded by default\)
> In the configuration file, the **priority** field \(the value is an integer ranging from 0 to 200\) indicates the priority of the host and driver. For drivers in different hosts, a smaller host priority value indicates a higher driver loading priority; for drivers in the same host, a smaller driver priority value indicates a higher driver loading priority.
......@@ -2,18 +2,20 @@
- [HDF Configuration Overview](#section59914284576)
- [Configuration Syntax](#section533713333580)
- [Keywords](#section1316625413586)
- [Basic Syntax](#section173481622115918)
- [Data Types](#section96521601302)
- [Pre-processing](#section8164295515)
- [Commenting](#section0338205819610)
- [Modifying a Reference](#section179799204716)
- [Replicating Node Configuration](#section382424014712)
- [Deleting a Node or Attribute](#section165211112586)
- [Referencing an Attribute](#section192841514490)
- [Keyword Template](#section520134294)
- [Keywords](#section4522107333)
- [Basic Structures](#section853042911312)
- [Data Types](#section177001259134)
- [Pre-Processing](#section14867121641)
- [Comments](#section1323412417)
- [Reference Modifications](#section193708571145)
- [Node Replication](#section1487792020513)
- [Delete](#section1096515391155)
- [Attribute References](#section20271317611)
- [Template](#section958819191063)
- [Configuration Generation](#section106152531919)
- [Introduction to HC-GEN](#section8260625101012)
- [Introduction to hc-gen](#section359734416616)
## HDF Configuration Overview<a name="section59914284576"></a>
......@@ -26,10 +28,8 @@ HDF Configuration Generator \(HC-GEN\) is a tool for converting a configuration
The following figure shows the typical application scenario of the HCB mode.
**Figure 1** Process of using HCS<a name="fig814111371944"></a>
![](figure/en-us_image_0000001053405727.png)
**Figure 1** Configuration process<a name="fig772653312159"></a>
![](figures/configuration-process.png "configuration-process")
The HCS is compiled using the HC-GEN tool to generate an HCB file. The HCS Parser module in the HDF recreates a configuration tree using the HCB file. Then, the HDF driver modules obtain the configurations using the API provided by the HCS Paser.
......@@ -37,7 +37,7 @@ The HCS is compiled using the HC-GEN tool to generate an HCB file. The HCS Parse
The HCS syntax is described as follows:
## Keywords<a name="section1316625413586"></a>
### Keywords<a name="section4522107333"></a>
The keywords listed in the following table below are reserved for HCS configuration files.
......@@ -90,7 +90,7 @@ The keywords listed in the following table below are reserved for HCS configurat
</tbody>
</table>
## Basic Syntax<a name="section173481622115918"></a>
### Basic Structures<a name="section853042911312"></a>
The HCS configuration file consists of configurations of attributes and nodes.
......@@ -106,7 +106,7 @@ An attribute, as the minimum configuration unit, is an independent configuration
- Available formats of **value** are as follows:
- A binary, octal, decimal, or hexadecimal integer. For details, see [Data Types](#section96521601302).
- A binary, octal, decimal, or hexadecimal integer. For details, see [Data Types](#section177001259134).
- A character string. The content should be enclosed in double quotation marks \(" "\).
......@@ -137,9 +137,9 @@ A node is a set of attributes. Its syntax is as follows:
- The **match\_attr** attribute can be added to a node. Its value is a globally unique character string. During configuration parsing, the query interface can be invoked to query the nodes with the attribute based on the attribute value.
## Data Types<a name="section96521601302"></a>
### Data Types<a name="section177001259134"></a>
Attributes automatically use built-in data types, including integers, strings, arrays, and booleans. You do not need to explicitly specify the data type for the attribute values.
Attributes automatically use built-in data types, including integer, string, array, and boolean. You do not need to explicitly specify the data type for the attribute values.
**Integer**
......@@ -170,7 +170,7 @@ attr_bar = ["hello", "world"];
A Boolean data type has two possible values: **true** and **false**.
## Pre-processing<a name="section8164295515"></a>
### Pre-Processing<a name="section14867121641"></a>
**include**
......@@ -184,7 +184,7 @@ The **include** keyword is used to import other HCS files. The syntax is as fo
- The file names must be enclosed by double quotation marks \(" "\). Files in different directories can be referenced using relative paths. The file included must be a valid HCS file.
- In the scenario that multiple HCS files are imported using **include**, if the same nodes exist, the latter node will override the former one, and other nodes are listed in sequence.
## Commenting<a name="section0338205819610"></a>
### Comments<a name="section1323412417"></a>
Comments can be formatted as follows:
......@@ -206,7 +206,7 @@ Comments can be formatted as follows:
>Multi-line comments cannot be nested.
## Modifying a Reference<a name="section179799204716"></a>
### Reference Modifications<a name="section193708571145"></a>
You can use the following syntax to modify the content of any other node:
......@@ -258,7 +258,7 @@ In the preceding example, the **foo.foo\_** node changes the value of the refe
- A node of the same level can be referenced simply using the node name. A node of a different level must be referenced by the absolute path, and node names are separated using a period \(.\). **root** indicates the root node. The path format is the node path sequence starting with root. For example, **root.foo.bar** is a valid absolute path.
- If multiple modifications are made to the same attribute, only one uncertain modification can take effect, and a warning will be displayed.
## Replicating Node Configuration<a name="section382424014712"></a>
### Node Replication<a name="section1487792020513"></a>
The content of a node can be replicated to another node to define the node with similar content. The syntax is as follows:
......@@ -297,9 +297,9 @@ root {
In the preceding example, the **bar** node configuration includes both the **attr\_0** and **attr\_1** values. The modification to **attr\_0** in the **bar** node does not affect the **foo** node.
The path of the **foo** node is not required if the **foo** node and the **bar** node are of the same level. Otherwise, the absolute path must be used. For details, see [Modifying a Reference](#section179799204716).
The path of the **foo** node is not required if the **foo** node and the **bar** node are of the same level. Otherwise, the absolute path must be used. For details, see [Reference Modifications](#section193708571145).
## Deleting a Node or Attribute<a name="section165211112586"></a>
### Delete<a name="section1096515391155"></a>
You can use the keyword **delete** to delete unnecessary nodes or attributes in the base configuration tree imported by the **include** keyword. In the following example, **sample1.hcs** imports the configuration of **sample2.hcs** using **include**, and deletes the **attribute2** attribute and the **foo\_2** node using the **delete** keyword.
......@@ -333,7 +333,7 @@ root {
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The **delete** keyword cannot be used in the same HCS file. It is recommended that you delete unnecessary attributes directly from the configuration source code.
## Referencing an Attribute<a name="section192841514490"></a>
### Attribute References<a name="section20271317611"></a>
To quickly locate the associated node during configuration parsing, you can use the node as the value of the attribute and read the attribute to find the corresponding node. The syntax is as follows:
......@@ -353,7 +353,7 @@ node2 {
}
```
## Keyword Template<a name="section520134294"></a>
### Template<a name="section958819191063"></a>
The **template** keyword is used to generate nodes with strictly consistent syntax, thereby facilitating the traverse and management of nodes of the same type.
......@@ -398,7 +398,7 @@ In the preceding example, the **bar** and **bar\_1** nodes inherit the **fo
The HC-GEN tool is used to generate configurations. It checks the HCS configuration syntax and converts HCS source files into HCB files.
## Introduction to HC-GEN<a name="section8260625101012"></a>
### Introduction to hc-gen<a name="section359734416616"></a>
Parameter description:
......
......@@ -128,7 +128,7 @@ The development of driver service management includes compiling, binding, obtain
- Using the subscription mechanism
If the kernel sapce unaware of the time for loading drivers \(on the same host\), use the subscription mechanism provided by the HDF to subscribe to the drivers. After the drivers are loaded, the HDF releases the driver services to you. The implementation is as follows:
If the kernel mode is unaware of the time for loading drivers \(on the same host\), use the subscription mechanism provided by the HDF to subscribe to the drivers. After the drivers are loaded, the HDF releases the driver services to you. The implementation is as follows:
```
// Subscription callback function. After the subscribed drivers are loaded, the HDF releases the driver services to you using this function.
......
......@@ -6,7 +6,7 @@
- **[Driver Service Management](driver-hdf-servicemanage.md)**
- **[Driver Message Mechanism Management](driver-hdf-news.md)**
- **[Driver Message Mechanism Management](driver-hdf-message-management.md)**
- **[Driver Configuration Management](driver-hdf-manage.md)**
......
......@@ -2,21 +2,17 @@
- [Overview](#section729758162218)
- [WLAN Driver API Architecture](#section178022416377)
- [Available APIs](#section149681312202415)
- [Development Guidelines](#section15957746172412)
- [How to Develop](#section11776186132513)
- [Available APIs](#section7331102018815)
- [How to Develop](#section15957746172412)
- [Development Example](#section1395253612512)
## Overview<a name="section729758162218"></a>
The WLAN module is developed based on the Hardware Driver Foundation \(HDF\). It supports cross-OS migration, component adaptation, and modular assembly and compilation. Based on the unified APIs provided by the WLAN module, driver developers of WLAN vendors can adapt their driver code and are capable of creating, disabling, scanning, and connecting to WLAN hotspots. The WLAN driver provides the Hardware Driver Interface \(HDI\) layer with the capabilities of setting and obtaining the device MAC address and setting the transmit power. The following figure shows the framework of the [WLAN module](#fig967034316227):
**Figure 1** WLAN framework<a name="fig967034316227"></a>
The WLAN module is developed based on the Hardware Driver Foundation \(HDF\). It supports cross-OS migration, component adaptation, and modular assembly and compilation. Based on the unified APIs provided by the WLAN module, driver developers of WLAN vendors can adapt their driver code and are capable of creating, disabling, scanning, and connecting to WLAN hotspots. The WLAN driver provides the Hardware Driver Interface \(HDI\) layer with the capabilities of setting and obtaining the device MAC address and setting the transmit power. The following figure shows the framework of the WLAN module:
![](figure/en-us_image_0000001170383063.png)
**Figure 1** WLAN framework<a name="fig4415112614415"></a>
![](figures/wlan-framework.png "wlan-framework")
### WLAN Driver API Architecture<a name="section178022416377"></a>
......@@ -28,12 +24,10 @@ The WLAN module provides the following three types of APIs:
3. Capability APIs for vendors
**Figure 2** Available APIs of the WLAN module<a name="fig15016395217"></a>
**Figure 2** Available APIs of the WLAN module<a name="fig1492411431166"></a>
![](figures/available-apis-of-the-wlan-module.png "available-apis-of-the-wlan-module")
![](figure/接口分布图4.png)
### Available APIs<a name="section149681312202415"></a>
## Available APIs<a name="section7331102018815"></a>
The WLAN driver module provides APIs that can be directly called by driver developers, such as creating/releasing a **WifiModule**, connecting to/disconnecting from a WLAN hotspot, applying for/releasing a **NetBuf**, and converting between the **pbuf** structure of Lightweight IP \(lwIP\) and a **NetBuf**. [Table 1](#table1521573319472) describes some APIs.
......@@ -232,12 +226,10 @@ The WLAN driver provides the HDI layer with the APIs for creating and destroying
</tbody>
</table>
## Development Guidelines<a name="section15957746172412"></a>
## How to Develop<a name="section15957746172412"></a>
The WLAN driver is developed based on the HDF and PLATFORM. It provides a unified driver model for WLAN modules of different vendors regardless of the operating system \(OS\) and system on a chip \(SoC\).
### How to Develop<a name="section11776186132513"></a>
1. Set hardware parameters such as **module** \(different features\) and **chip** in the **wifi\_config.hcs** file.
2. Parse the **wifi\_config.hcs** file and generate a structure with the configured parameters.
3. Initialize and create a module.
......
# LCD<a name="EN-US_TOPIC_0000001052857284"></a>
- [Overview](#section141575391542)
- [API Description](#section14711163785519)
- [Development Guidelines](#section12394223125615)
- [How to Develop](#section515923045814)
- [API Description](#section53793327396)
- [How to Develop](#section12394223125615)
- [Development Example](#section7441155155813)
## Overview<a name="section141575391542"></a>
......@@ -13,48 +10,43 @@
The Liquid Crystal Display \(LCD\) driver powers on the LCD and initializes internal LCD registers through APIs to enable the LCD to work properly. The display driver is developed based on the hardware driver foundation \([HDF](driver-hdf-overview.md)\). It provides power-on, power-off, and sending of the initialization sequence for LCD hardware across OSs and platforms. The display driver model is shown in [Figure 1](#fig69138814229).
**Figure 1** Architecture of the display driver model<a name="fig69138814229"></a>
![](figure/architecture-of-the-display-driver-model.png "architecture-of-the-display-driver-model")
- **Display driver model**
![](figures/architecture-of-the-display-driver-model.png "architecture-of-the-display-driver-model")
The display driver model consists of the display common driver layer, SoC adapter layer, and third-party chip driver layer. The display driver model is developed based on the HDF and hides the differences between kernel forms through platform and OSAL APIs so the LCD driver can be migrated between different OSs and chip platforms. The display driver connects to the display common HAL, supports the implementation of Hardware Driver Interfaces \(HDIs\), and provides various driver interfaces for the graphics service through the display HDI.
**Display driver model**
- Display common driver layer: connects to the display common HAL through the IOService data channel provided by the HDF to receive and process upper-layer calls in a centralized manner.
The display driver model consists of the display common driver layer, SoC adapter layer, and third-party chip driver layer. The display driver model is developed based on the HDF and hides the differences between kernel forms through platform and OSAL APIs so the LCD driver can be migrated between different OSs and chip platforms. The display driver connects to the display common HAL, supports the implementation of Hardware Driver Interfaces \(HDIs\), and provides various driver interfaces for the graphics service through the display HDI.
- SoC adapter layer: decouples the display driver from the SoC driver, configures parameters related to the chip platform, and passes calls from the platform driver layer to the LCD driver layer.
- HDF display driver layer: connects to the display common HAL through the IOService data channel provided by the HDF to receive and process various upper-layer calls in a centralized manner.
- SoC adapter layer: decouples the display driver from the SoC driver, configures parameters related to the chip platform, and passes the calls at the platform driver layer to the LCD driver layer.
- LCD panel driver layer: provides LCD-related APIs for sending the initialization sequence, powering on/off, and setting the backlight.
- Third-party chip driver layer: provides LCD-related APIs for sending the LCD initialization sequence, powering on or off the LCD device, and setting the backlight.
The display driver model, capabilities, and APIs help you simplify the display driver development and improve the efficiency.
The display driver model, capabilities, and APIs help you simplify the display driver development and improve the efficiency.
### API Description<a name="section14711163785519"></a>
## API Description<a name="section53793327396"></a>
The LCD interfaces are classified into the Mobile Industry Processor Interface \(MIPI\) Display Serial Interface \(DSI\), Transistor-Transistor Logic \(TTL\) interfaces, and Low Voltage Differential Signaling \(LVDS\) interfaces. The MIPI DSI and TTL interfaces are commonly used. Here is a brief introduction to them.
- MIPI DSI
**Figure 2** MIPI DSI<a name="fig6936451331"></a>
![](figure/mipi-dsi.png "mipi-dsi")
![](figures/mipi-dsi.png "mipi-dsi")
The MIPI DSI is defined by MIPI Alliance. It is mainly used for mobile terminal display. The MIPI DSI is used to transmit image data, in compliance with the MIPI protocol. Generally, control information of the MIPI DSI is sent to the peer IC in the form of MIPI packets through the MIPI DSI. No additional interface is required.
- TTL interface
**Figure 3** TTL interface<a name="fig141611855635"></a>
![](figure/ttl-interface.png "ttl-interface")
![](figures/ttl-interface.png "ttl-interface")
TTL level signals are generated by TTL devices, which are a major type of digital integrated circuits. They are manufactured using the bipolar process and feature high speed, low power consumption, and multiple types.
The TTL interface is used to transmit data in parallel mode under the control of control signals. It transmits data signals, clock signals, and control signals \(such as line synchronization signals, frame synchronization signals, and data validity signals\). Generally, the LCD of the TTL interface and the read/write of internal registers require additional peripheral interfaces, such as the Serial Peripheral Interface \(SPI\) and Inter-Integrated Circuit \(I2C\).
## Development Guidelines<a name="section12394223125615"></a>
## How to Develop<a name="section12394223125615"></a>
The display driver model is developed based on the HDF, platform APIs, and APIs at the OS abstraction layer \(OSAL\), and provides a unified driver model for the LCD regardless of the OS \(LiteOS or Linux OS\) and chip platforms \(such as Hi35xx, Hi38xx, and V3S\).
### How to Develop<a name="section515923045814"></a>
1. Add the LCD driver-related hardware descriptions.
2. Add a driver that adapts to the chip at the SoC adapter layer.
3. Add the LCD panel driver and register the panel driver functions in the driver entry function **Init**. The functions provide capabilities for:
......
# Sensor<a name="EN-US_TOPIC_0000001078401780"></a>
- [Overview](#section3634112111)
- [Available APIs](#section188213414114)
- [Development Guidelines](#section1140943382)
- [How to Develop](#section7893102915819)
- [Available APIs](#section20930112117478)
- [How to Develop](#section1140943382)
- [Development Example](#section257750691)
- [Test Guidelines](#section106021256121219)
......@@ -14,7 +11,7 @@
The sensor driver module provides APIs for upper-layer sensor services to implement basic sensor capabilities, including querying the sensor list, enabling or disabling a sensor, subscribing to or unsubscribing from sensor data, and setting sensor options. The sensor driver model is developed based on the Hardware Driver Foundation \(HDF\) and supports functions such as cross-OS migration and differentiated device configuration. The following figure shows the architecture of the sensor driver model.
**Figure 1** Architecture of the sensor driver model<a name="fig10451455446"></a>
![](figure/architecture-of-the-sensor-driver-model.png "architecture-of-the-sensor-driver-model")
![](figures/architecture-of-the-sensor-driver-model.png "architecture-of-the-sensor-driver-model")
The sensor driver model offers the following APIs:
......@@ -22,7 +19,7 @@ The sensor driver model offers the following APIs:
- APIs for implementing sensor driver model capabilities: These APIs implement the capabilities of registering, loading, and unregistering sensor drivers as well as detecting sensor devices depending on the HDF. The APIs include normalized APIs for sensor devices of the same type, APIs for parsing register configurations, abstract APIs for bus access, and abstract platform APIs.
- APIs to be implemented by developers: Based on the HDF Configuration Source \(HCS\), developers can implement differentiated configuration for sensors of the same type and serialized configuration of sensor device parameters. Some sensor device operations can be abstracted as APIs to simplify sensor driver development.
### Available APIs<a name="section188213414114"></a>
## Available APIs<a name="section20930112117478"></a>
The following table lists the APIs provided by the sensor driver model.
......@@ -248,12 +245,10 @@ The following table lists the APIs that need to be implemented by driver develop
For details about the API implementation, see [Development Example](#section257750691).
## Development Guidelines<a name="section1140943382"></a>
## How to Develop<a name="section1140943382"></a>
Regardless of the OS and system on a chip \(SoC\), the sensor driver is developed based on the HDF, platform, and OSAL APIs to provide a unified driver model for sensor devices. This section uses the acceleration sensor as an example to describe how to develop a sensor driver.
### How to Develop<a name="section7893102915819"></a>
1. Register the acceleration sensor driver. The HDF provides a unified driver management model. The HDF identifies and loads the target module driver based on the configuration of the acceleration sensor module.
2. Initialize and deinitialize the acceleration sensor driver. Using the **init** function, the HDF starts loading the sensor device driver and allocating configuration resources for sensor device data, respectively. Using the **release** function, the HDF releases the resources and configurations loaded by the driver.
3. Parse the configurations of the acceleration sensor register group. For different types of sensors, you must configure their respective HCS configuration files in the HCS, check whether the sensor device is in position during the device driver startup, and then load the corresponding configuration file to generate the configuration structure object.
......
# TOUCHSCREEN<a name="EN-US_TOPIC_0000001052857350"></a>
- [Overview](#section175431838101617)
- [Available APIs](#section17667171301711)
- [Development Guidelines](#section65745222184)
- [How to Develop](#section865734181916)
- [Available APIs](#section105459441659)
- [How to Develop](#section65745222184)
- [Development Example](#section263714411191)
- [Add the touchscreen driver-related descriptions.](#section18249155619195)
- [Board-level Hardware Configuration and Private Data Configuration](#section3571192072014)
......@@ -27,7 +24,7 @@
**Figure 1** Architecture of the input driver model<a name="fig6251184817261"></a>
![](figure/architecture-of-the-input-driver-model.png "architecture-of-the-input-driver-model")
![](figures/architecture-of-the-input-driver-model.png "architecture-of-the-input-driver-model")
- **Input driver model**
......@@ -49,7 +46,7 @@
The touchscreen driver is developed based on the [HDF](driver-hdf-development.md) and is implemented via calls to the OSAL and platform APIs, including bus APIs and OS native APIs \(such as memory, lock, thread, and timer\). The OSAL and platform APIs hide the differences of underlying hardware, so that the touchscreen driver can be migrated across platforms and OSs. In this regard, you can develop the touchscreen driver only once but deploy it on multiple devices.
### Available APIs<a name="section17667171301711"></a>
## Available APIs<a name="section105459441659"></a>
Based on the attributes of the pins, interfaces on the touchscreens can be classified into the following types:
......@@ -58,7 +55,7 @@ Based on the attributes of the pins, interfaces on the touchscreens can be class
- Communications interfaces
**Figure 2** Common pins of the touchscreen<a name="fig1290384314416"></a>
![](figure/common-pins-of-the-touchscreen.png "common-pins-of-the-touchscreen")
![](figures/common-pins-of-the-touchscreen.png "common-pins-of-the-touchscreen")
The interfaces shown in the figure are described as follows:
......@@ -73,30 +70,29 @@ The interfaces shown in the figure are described as follows:
- INT: interrupt pin, which needs to be set to the input direction and pull-up status during driver initialization. After detecting an external touch signal, the driver triggers the interrupt by operating the interrupt pin. The driver reads the touch reporting data in the ISR function.
3. **Communications interfaces**
- I2C: Since only a small amount of touch data is reported by the touchscreen, I2C is used to transmit the reported data. For details about the I2C protocol and interfaces, see [I2C](driver-platform-i2c-des.md#section1695201514281).
- SPI: In addition to touch reporting data coordinates, some vendors need to obtain basic capacitance data. Therefore, Serial Peripheral Interface \(SPI\) is used to transmit such huge amount of data. For details about the SPI protocol and interfaces, see [SPI](driver-platform-spi-des.md#section71363452477).
- I2C: Since only a small amount of touch data is reported by the touchscreen, I2C is used to transmit the reported data. For details about the I2C protocol and interfaces, see [I2C](driver-platform-i2c-des.md#section5361140416).
- SPI: In addition to touch reporting data coordinates, some vendors need to obtain basic capacitance data. Therefore, Serial Peripheral Interface \(SPI\) is used to transmit such huge amount of data. For details about the SPI protocol and interfaces, see [SPI](driver-platform-spi-des.md#section193356154511).
## Development Guidelines<a name="section65745222184"></a>
## How to Develop<a name="section65745222184"></a>
Regardless of the OS and system on a chip \(SoC\), the input driver is developed based on the HDF, platform, and OSAL APIs to provide a unified driver model for touchscreen devices.
- The following uses the touchscreen driver as an example to describe the loading process of the input driver model:
\(1\) Complete the device description configuration, such as the loading priority, board-level hardware information, and private data, by referring to the existing template.
The following uses the touchscreen driver as an example to describe the loading process of the input driver model:
\(2\) Load the input device management driver. The input management driver is loaded automatically by the HDF to create and initialize the device manager.
\(1\) Complete the device description configuration, such as the loading priority, board-level hardware information, and private data, by referring to the existing template.
\(3\) Load the platform driver. The platform driver is loaded automatically by the HDF to parse the board-level configuration, initialize the hardware, and provide the API for registering the touchscreen.
\(2\) Load the input device management driver. The input management driver is loaded automatically by the HDF to create and initialize the device manager.
\(4\) Load the touchscreen driver. The touchscreen driver is loaded automatically by the HDF to instantiate the touchscreen device, parse the private data, and implement differentiated APIs provided by the platform.
\(3\) Load the platform driver. The platform driver is loaded automatically by the HDF to parse the board-level configuration, initialize the hardware, and provide the API for registering the touchscreen.
\(5\) Register the instantiated touchscreen device with the platform driver. Then bind this device to the platform driver, and complete touchscreen initialization such as interrupt registration and power-on and power-off.
\(4\) Load the touchscreen driver. The touchscreen driver is loaded automatically by the HDF to instantiate the touchscreen device, parse the private data, and implement differentiated APIs provided by the platform.
\(6\) Instantiate the input device and register it with the input manager after the touchscreen is initialized.
\(5\) Register the instantiated touchscreen device with the platform driver. Then bind this device to the platform driver, and complete touchscreen initialization such as interrupt registration and power-on and power-off.
\(6\) Instantiate the input device and register it with the input manager after the touchscreen is initialized.
### How to Develop<a name="section865734181916"></a>
Perform the following steps:
1. Add the touchscreen driver-related descriptions.
......@@ -108,7 +104,7 @@ Regardless of the OS and system on a chip \(SoC\), the input driver is developed
3. Implement differentiated adaptation APIs of the touchscreen.
Use the platform APIs to perform operations for the reset pins, interrupt pins, and power based on the communications interfaces designed for boards. For details about the GPIO-related operations, see [GPIO](driver-platform-gpio-des.md#section259614242196).
Use the platform APIs to perform operations for the reset pins, interrupt pins, and power based on the communications interfaces designed for boards. For details about the GPIO-related operations, see [GPIO](driver-platform-gpio-des.md#section1635911016188).
## Development Example<a name="section263714411191"></a>
......
# Peripheral Driver Development<a name="EN-US_TOPIC_0000001157319411"></a>
# Peripheral Driver Usage<a name="EN-US_TOPIC_0000001157319411"></a>
- **[LCD](driver-peripherals-lcd-des.md)**
......
# ADC<a name="EN-US_TOPIC_0000001153677754"></a>
- [Overview](#section268031773165048)
- [How to Develop](#section100579767165048)
- [AdcMethod](#section1618135285210)
- [Development Example](#section1745221471165048)
## Overview<a name="section268031773165048"></a>
The analog-to-digital converter \(ADC\) is a device that converts analog signals into digital signals. In the Hardware Driver Foundation \(HDF\) framework, 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.
**Figure 1** Unified service mode<a name="fig14423182615525"></a>
![](figures/unified-service-mode.png "unified-service-mode")
## How to Develop<a name="section100579767165048"></a>
The ADC 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **adc\_config.hcs** file.
3. Instantiate the ADC controller object.
- Initialize **AdcDevice**.
- Instantiate **AdcMethod** in the **AdcDevice** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [AdcMethod](#section1618135285210) and [Table 1](#table1943202316536).
4. Debug the driver.
- \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the signal collection is successful.
### AdcMethod<a name="section1618135285210"></a>
```
struct AdcMethod {
int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val);
int32_t (*start)(struct AdcDevice *device);
int32_t (*stop)(struct AdcDevice *device);
};
```
**Table 1** Callbacks for the members in the AdcMethod structure
<a name="table1943202316536"></a>
<table><thead align="left"><tr id="row2451223135315"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p845123185313"><a name="p845123185313"></a><a name="p845123185313"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p345192315311"><a name="p345192315311"></a><a name="p345192315311"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p74512313536"><a name="p74512313536"></a><a name="p74512313536"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p174542313531"><a name="p174542313531"></a><a name="p174542313531"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p445112315535"><a name="p445112315535"></a><a name="p445112315535"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row545102316536"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p14562345312"><a name="p14562345312"></a><a name="p14562345312"></a>read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p474720389561"><a name="p474720389561"></a><a name="p474720389561"></a><strong id="b167472038115611"><a name="b167472038115611"></a><a name="b167472038115611"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p>
<p id="p14459238536"><a name="p14459238536"></a><a name="p14459238536"></a><strong id="b179891252205514"><a name="b179891252205514"></a><a name="b179891252205514"></a>channel</strong>: channel ID of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p746423195320"><a name="p746423195320"></a><a name="p746423195320"></a><strong id="b626111125816"><a name="b626111125816"></a><a name="b626111125816"></a>val</strong>: pointer to the signal data to be transmitted. It is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1746192315311"><a name="p1746192315311"></a><a name="p1746192315311"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p146152311537"><a name="p146152311537"></a><a name="p146152311537"></a>Reads the signal data sampled by the ADC.</p>
</td>
</tr>
<tr id="row6461236531"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p446182316538"><a name="p446182316538"></a><a name="p446182316538"></a>stop</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1446112318536"><a name="p1446112318536"></a><a name="p1446112318536"></a><strong id="b345886135912"><a name="b345886135912"></a><a name="b345886135912"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p4461823125317"><a name="p4461823125317"></a><a name="p4461823125317"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1346122314530"><a name="p1346122314530"></a><a name="p1346122314530"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1346223185318"><a name="p1346223185318"></a><a name="p1346223185318"></a>Stops the ADC device.</p>
</td>
</tr>
<tr id="row194622375313"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p144642305313"><a name="p144642305313"></a><a name="p144642305313"></a>start</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p17461323185314"><a name="p17461323185314"></a><a name="p17461323185314"></a><strong id="b1988212105110"><a name="b1988212105110"></a><a name="b1988212105110"></a>device</strong>: structure pointer to the ADC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1146623105317"><a name="p1146623105317"></a><a name="p1146623105317"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p546132311535"><a name="p546132311535"></a><a name="p546132311535"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1471623195311"><a name="p1471623195311"></a><a name="p1471623195311"></a>Starts the ADC device.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1745221471165048"></a>
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.
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 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.
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.
- ADC driver entry reference
Many devices may connect to the ADC. In the HDF framework, 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.
```
static struct HdfDriverEntry g_hi35xxAdcDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxAdcInit,
.Release = Hi35xxAdcRelease,
.moduleName = "hi35xx_adc_driver",// (Mandatory) This parameter must be the same as that in the .hcs file.
};
HDF_INIT(g_hi35xxAdcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework.
// Driver entry of the adc_core.c manager service at the core layer
struct HdfDriverEntry g_adcManagerEntry = {
.moduleVersion = 1,
.Init = AdcManagerInit,
.Release = AdcManagerRelease,
.moduleName = "HDF_PLATFORM_ADC_MANAGER",// This parameter corresponds to device0 in the device_info file.
};
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.
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:
<a name="table1344068233165048"></a>
<table><thead align="left"><tr id="row1551612465165048"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1856185125165048p0"><a name="entry1856185125165048p0"></a><a name="entry1856185125165048p0"></a>Member</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry720672143165048p0"><a name="entry720672143165048p0"></a><a name="entry720672143165048p0"></a>Value</p>
</th>
</tr>
</thead>
<tbody><tr id="row583452627165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry747665129165048p0"><a name="entry747665129165048p0"></a><a name="entry747665129165048p0"></a>moduleName</p>
</td>
<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>
</tr>
<tr id="row218211231165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry568759156165048p0"><a name="entry568759156165048p0"></a><a name="entry568759156165048p0"></a>serviceName</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1349637957165048p0"><a name="entry1349637957165048p0"></a><a name="entry1349637957165048p0"></a>–</p>
</td>
</tr>
<tr id="row1166331861165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1142726988165048p0"><a name="entry1142726988165048p0"></a><a name="entry1142726988165048p0"></a>policy</p>
</td>
<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>
</tr>
<tr id="row1822624516165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry982991296165048p0"><a name="entry982991296165048p0"></a><a name="entry982991296165048p0"></a>deviceMatchAttr</p>
</td>
<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 {
device_info {
platform :: host {
device_adc :: device {
device0 :: deviceNode {
policy = 0;
priority = 50;
permission = 0644;
moduleName = "HDF_PLATFORM_ADC_MANAGER";
serviceName = "HDF_PLATFORM_ADC_MANAGER";
}
device1 :: deviceNode {
policy = 0; // The value 0 indicates that no service needs to be published.
priority = 55; // Driver startup priority
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.
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.
} // The specific controller information is in adc_config.hcs.
}
}
}
}
```
- adc\_config.hcs configuration reference
```
root {
platform {
adc_config_hi35xx {
match_attr = "hisilicon_hi35xx_adc";
template adc_device {
regBasePhy = 0x120e0000;// Physical base address of the register
regSize = 0x34; // Bit width of the register
deviceNum = 0; // Device number
validChannel = 0x1; // Valid channel
dataWidth = 10; // Data bit width of received signals
scanMode = 1; // Scan mode
delta = 0; // Delta parameter
deglitch = 0;
glitchSample = 5000;
rate = 20000;
}
device_0 :: adc_device {
deviceNum = 0;
validChannel = 0x2;
}
}
}
}
```
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**\).
- Custom structure reference
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 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 *pinCtrlBase;
uint32_t regBasePhy; // (Mandatory) Physical base address of the register
uint32_t regSize; // (mandatory) Bit width of the register
uint32_t deviceNum; // (Mandatory) Device number
uint32_t dataWidth; // (Mandatory) Data bit width of received signals
uint32_t validChannel; // (Mandatory) Valid channel
uint32_t scanMode; // (Mandatory) Scan mode
uint32_t delta;
uint32_t deglitch;
uint32_t glitchSample;
uint32_t rate; // (Mandatory) Sampling rate
};
// AdcDevice is the core layer controller structure. Its members are assigned with values by using the Init function.
struct AdcDevice {
const struct AdcMethod *ops;
OsalSpinlock spin;
uint32_t devNum;
uint32_t chanNum;
const struct AdcLockMethod *lockOps;
void *priv;
};
```
- 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.
```
static const struct AdcMethod g_method = {
.read = Hi35xxAdcRead,
.stop = Hi35xxAdcStop,
.start = Hi35xxAdcStart,
};
```
- Init 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.\)
<a name="table127573104165048"></a>
<table><thead align="left"><tr id="row1932243367165048"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry405408385165048p0"><a name="entry405408385165048p0"></a><a name="entry405408385165048p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry407875094165048p0"><a name="entry407875094165048p0"></a><a name="entry407875094165048p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1845195554165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry144793493165048p0"><a name="entry144793493165048p0"></a><a name="entry144793493165048p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1933449399165048p0"><a name="entry1933449399165048p0"></a><a name="entry1933449399165048p0"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row1203086670165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry766973904165048p0"><a name="entry766973904165048p0"></a><a name="entry766973904165048p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry999036326165048p0"><a name="entry999036326165048p0"></a><a name="entry999036326165048p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1147526196165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry271913224165048p0"><a name="entry271913224165048p0"></a><a name="entry271913224165048p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1349459344165048p0"><a name="entry1349459344165048p0"></a><a name="entry1349459344165048p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row42206428165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry826579070165048p0"><a name="entry826579070165048p0"></a><a name="entry826579070165048p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry740637684165048p0"><a name="entry740637684165048p0"></a><a name="entry740637684165048p0"></a>I/O error</p>
</td>
</tr>
<tr id="row456623770165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry2126491887165048p0"><a name="entry2126491887165048p0"></a><a name="entry2126491887165048p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1585614415165048p0"><a name="entry1585614415165048p0"></a><a name="entry1585614415165048p0"></a>Transmission successful</p>
</td>
</tr>
<tr id="row2048732992165048"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry131232818165048p0"><a name="entry131232818165048p0"></a><a name="entry131232818165048p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry42178503165048p0"><a name="entry42178503165048p0"></a><a name="entry42178503165048p0"></a>Transmission failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **AdcDevice**, and calls the **AdcDeviceAdd** function at the core layer.
```
static int32_t Hi35xxAdcInit(struct HdfDeviceObject *device)
{
int32_t ret;
struct DeviceResourceNode *childNode = NULL;
...
// Traverse and parse all nodes in adc_config.hcs and call the Hi35xxAdcParseInit function to initialize the devices separately.
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
ret = Hi35xxAdcParseInit(device, childNode);// For details about the function definition, see the following description.
...
}
return ret;
}
static int32_t Hi35xxAdcParseInit(struct HdfDeviceObject *device, struct DeviceResourceNode *node)
{
int32_t ret;
struct Hi35xxAdcDevice *hi35xx = NULL; // (Mandatory) Custom structure object
(void)device;
hi35xx = (struct Hi35xxAdcDevice *)OsalMemCalloc(sizeof(*hi35xx)); // (Mandatory) Memory allocation
...
ret = Hi35xxAdcReadDrs(hi35xx, node); // (Mandatory) Fill the default values in the adc_config file to the structure.
...
hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);// (Mandatory) Address mapping
...
hi35xx->pinCtrlBase = OsalIoRemap(HI35XX_ADC_IO_CONFIG_BASE, HI35XX_ADC_IO_CONFIG_SIZE);
...
Hi35xxAdcDeviceInit(hi35xx); // (Mandatory) Initialize the ADC.
hi35xx->device.priv = (void *)node; // (Mandatory) Store device attributes.
hi35xx->device.devNum = hi35xx->deviceNum;// (Mandatory) Initialize the AdcDevice members.
hi35xx->device.ops = &g_method; // (Mandatory) Mount 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.
...
return HDF_SUCCESS;
__ERR__:
if (hi35xx != NULL) { // If the operation fails, you need to execute the initialization function reversely.
if (hi35xx->regBase != NULL) {
OsalIoUnmap((void *)hi35xx->regBase);
hi35xx->regBase = NULL;
}
AdcDeviceRemove(&hi35xx->device);
OsalMemFree(hi35xx);
}
return ret;
}
```
- 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 framework 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.
```
static void Hi35xxAdcRelease(struct HdfDeviceObject *device)
{
const struct DeviceResourceNode *childNode = NULL;
...
// Traverse and parse all nodes in adc_config.hcs and perform the release operation on each node.
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
Hi35xxAdcRemoveByNode(childNode);// The function definition is as follows:
}
}
static void Hi35xxAdcRemoveByNode(const struct DeviceResourceNode *node)
{
int32_t ret;
int32_t deviceNum;
struct AdcDevice *device = NULL;
struct Hi35xxAdcDevice *hi35xx = NULL;
struct DeviceResourceIface *drsOps = NULL;
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
...
ret = drsOps->GetUint32(node, "deviceNum", (uint32_t *)&deviceNum, 0);
...
// You can call the AdcDeviceGet function to obtain the AdcDevice object based on deviceNum and call the AdcDeviceRemove function to release the AdcDevice object.
device = AdcDeviceGet(deviceNum);
if (device != NULL && device->priv == node) {
AdcDevicePut(device);
AdcDeviceRemove(device); // (Mandatory) Remove the AdcDevice object from the driver manager.
hi35xx = (struct Hi35xxAdcDevice *)device;// (Mandatory) Obtain the custom object through forced conversion and release the object.
OsalIoUnmap((void *)hi35xx->regBase);
OsalMemFree(hi35xx);
}
return
```
# GPIO<a name="EN-US_TOPIC_0000001051777586"></a>
# GPIO<a name="EN-US_TOPIC_0000001206171135"></a>
- [Overview](#section1635911016188)
- [Available APIs](#section17715915181611)
- [Available APIs](#section589913442203)
- [Usage Guidelines](#section259614242196)
- [How to Use](#section103477714216)
- [Determining a GPIO Pin Number](#section370083272117)
......@@ -22,63 +21,63 @@ The GPIO APIs define a set of standard functions for performing operations on GP
- Setting an interrupt service routine \(ISR\) function and interrupt trigger mode for a pin
- Enabling or disabling a pin interrupt
### Available APIs<a name="section17715915181611"></a>
## Available APIs<a name="section589913442203"></a>
**Table 1** APIs available for the GPIO driver
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" valign="top" width="19.74%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>Capability</p>
<a name="table89681075215"></a>
<table><thead align="left"><tr id="row996807162115"><th class="cellrowborder" valign="top" width="19.74%" id="mcps1.2.4.1.1"><p id="p296817716212"><a name="p296817716212"></a><a name="p296817716212"></a>Capability</p>
</th>
<th class="cellrowborder" valign="top" width="32.36%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>Function</p>
<th class="cellrowborder" valign="top" width="32.36%" id="mcps1.2.4.1.2"><p id="p596897172119"><a name="p596897172119"></a><a name="p596897172119"></a>Function</p>
</th>
<th class="cellrowborder" valign="top" width="47.9%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>Description</p>
<th class="cellrowborder" valign="top" width="47.9%" id="mcps1.2.4.1.3"><p id="p39681677213"><a name="p39681677213"></a><a name="p39681677213"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row34145016535"><td class="cellrowborder" rowspan="2" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>GPIO read/write</p>
<tbody><tr id="row896847202113"><td class="cellrowborder" rowspan="2" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p1796814719210"><a name="p1796814719210"></a><a name="p1796814719210"></a>GPIO read/write</p>
</td>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>GpioRead</p>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p39683732112"><a name="p39683732112"></a><a name="p39683732112"></a>GpioRead</p>
</td>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p8738101941716"><a name="p8738101941716"></a><a name="p8738101941716"></a>Reads the level value of a GPIO pin.</p>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p59687710219"><a name="p59687710219"></a><a name="p59687710219"></a>Reads the level value of a GPIO pin.</p>
</td>
</tr>
<tr id="row5632152611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p143890309153"><a name="p143890309153"></a><a name="p143890309153"></a>GpioWrite</p>
<tr id="row17968872212"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p396812722116"><a name="p396812722116"></a><a name="p396812722116"></a>GpioWrite</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p67306152404"><a name="p67306152404"></a><a name="p67306152404"></a>Writes the level value of a GPIO pin.</p>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p396814715219"><a name="p396814715219"></a><a name="p396814715219"></a>Writes the level value of a GPIO pin.</p>
</td>
</tr>
<tr id="row17493124814141"><td class="cellrowborder" rowspan="2" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p321814526178"><a name="p321814526178"></a><a name="p321814526178"></a>GPIO settings</p>
<tr id="row129681576218"><td class="cellrowborder" rowspan="2" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p1496813782116"><a name="p1496813782116"></a><a name="p1496813782116"></a>GPIO settings</p>
</td>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p16390153015156"><a name="p16390153015156"></a><a name="p16390153015156"></a>GpioSetDir</p>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p29688742119"><a name="p29688742119"></a><a name="p29688742119"></a>GpioSetDir</p>
</td>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p1873761519408"><a name="p1873761519408"></a><a name="p1873761519408"></a>Sets the direction for a GPIO pin.</p>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p179682792111"><a name="p179682792111"></a><a name="p179682792111"></a>Sets the direction for a GPIO pin.</p>
</td>
</tr>
<tr id="row10681146181417"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p15390153014151"><a name="p15390153014151"></a><a name="p15390153014151"></a>GpioGetDir</p>
<tr id="row1196817715217"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p896827182120"><a name="p896827182120"></a><a name="p896827182120"></a>GpioGetDir</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p974061515406"><a name="p974061515406"></a><a name="p974061515406"></a>Obtains the direction for a GPIO pin.</p>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p39689792111"><a name="p39689792111"></a><a name="p39689792111"></a>Obtains the direction for a GPIO pin.</p>
</td>
</tr>
<tr id="row10288191441518"><td class="cellrowborder" rowspan="4" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p13927416134716"><a name="p13927416134716"></a><a name="p13927416134716"></a>GPIO interrupt settings</p>
<tr id="row69682071217"><td class="cellrowborder" rowspan="4" valign="top" width="19.74%" headers="mcps1.2.4.1.1 "><p id="p296818714213"><a name="p296818714213"></a><a name="p296818714213"></a>GPIO interrupt settings</p>
</td>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p17390113013158"><a name="p17390113013158"></a><a name="p17390113013158"></a>GpioSetIrq</p>
<td class="cellrowborder" valign="top" width="32.36%" headers="mcps1.2.4.1.2 "><p id="p1396916710216"><a name="p1396916710216"></a><a name="p1396916710216"></a>GpioSetIrq</p>
</td>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p10314104354416"><a name="p10314104354416"></a><a name="p10314104354416"></a>Sets the ISR function for a GPIO pin.</p>
<td class="cellrowborder" valign="top" width="47.9%" headers="mcps1.2.4.1.3 "><p id="p99693712113"><a name="p99693712113"></a><a name="p99693712113"></a>Sets the ISR function for a GPIO pin.</p>
</td>
</tr>
<tr id="row163795912473"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p523618345323"><a name="p523618345323"></a><a name="p523618345323"></a>GpioUnSetIrq</p>
<tr id="row4969117172110"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p119692079215"><a name="p119692079215"></a><a name="p119692079215"></a>GpioUnSetIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1138195912478"><a name="p1138195912478"></a><a name="p1138195912478"></a>Cancels the setting of the ISR function for a GPIO pin.</p>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p1996916792114"><a name="p1996916792114"></a><a name="p1996916792114"></a>Cancels the setting of the ISR function for a GPIO pin.</p>
</td>
</tr>
<tr id="row155161515124816"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p657344273218"><a name="p657344273218"></a><a name="p657344273218"></a>GpioEnableIrq</p>
<tr id="row396907112117"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p109694717216"><a name="p109694717216"></a><a name="p109694717216"></a>GpioEnableIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p115163154488"><a name="p115163154488"></a><a name="p115163154488"></a>Enables a GPIO interrupt.</p>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p2969473216"><a name="p2969473216"></a><a name="p2969473216"></a>Enables a GPIO interrupt.</p>
</td>
</tr>
<tr id="row1742119174820"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1865114616324"><a name="p1865114616324"></a><a name="p1865114616324"></a>GpioDisableIrq</p>
<tr id="row14969117152113"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p18969157182116"><a name="p18969157182116"></a><a name="p18969157182116"></a>GpioDisableIrq</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p97421219174820"><a name="p97421219174820"></a><a name="p97421219174820"></a>Disables a GPIO interrupt.</p>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19690710214"><a name="p19690710214"></a><a name="p19690710214"></a>Disables a GPIO interrupt.</p>
</td>
</tr>
</tbody>
......@@ -91,12 +90,10 @@ The GPIO APIs define a set of standard functions for performing operations on GP
### How to Use<a name="section103477714216"></a>
The GPIO APIs use the GPIO pin number to specify a pin. [Figure 1](#fig1399416053717) shows the general process of using a GPIO.
**Figure 1** Process of using a GPIO<a name="fig1399416053717"></a>
The GPIO APIs use the GPIO pin number to specify a pin. [Figure 1](#fig16151101653713) shows the general process of using a GPIO.
![](figure/en-us_image_0000001170187071.png)
**Figure 1** Process of using a GPIO<a name="fig16151101653713"></a>
![](figures/process-of-using-a-gpio.png "process-of-using-a-gpio")
### Determining a GPIO Pin Number<a name="section370083272117"></a>
......
# GPIO<a name="EN-US_TOPIC_0000001153555758"></a>
- [Overview](#section1826197354103451)
- [How to Develop](#section731175315103451)
- [GpioMethod](#section20369125172319)
- [Development Example](#section800425816103451)
- [\#section83834353114](#section83834353114)
## Overview<a name="section1826197354103451"></a>
In the Hardware Driver Foundation \(HDF\) framework, the general-purpose input/output \(GPIO\) module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object.
**Figure 1** Service-free mode<a name="fig5511033193814"></a>
![](figures/service-free-mode.png "service-free-mode")
## How to Develop<a name="section731175315103451"></a>
The GPIO controller manages all pins by group. The related parameters are described in the attribute file. Instantiating the driver entry and API functions is the core for the vendor driver to access the HDF.
The GPIO 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **gpio\_config.hcs** file.
3. Instantiate the GPIO controller object.
- Initialize **GpioCntlr**.
- Instantiate **GpioMethod** in the **GpioCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [GpioMethod](#section20369125172319) and [Table 1](#table151341544111).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the GPIO control status and response to interrupts.
### GpioMethod<a name="section20369125172319"></a>
```
struct GpioMethod {
int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);// (Optional)
int32_t (*release)(struct GpioCntlr *cntlr, uint16_t local);// (Optional)
int32_t (*write)(struct GpioCntlr *cntlr, uint16_t local, uint16_t val);
int32_t (*read)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val);
int32_t (*setDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir);
int32_t (*getDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir);
int32_t (*toIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);// (Optional)
int32_t (*setIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode, GpioIrqFunc func, void *arg);
int32_t (*unsetIrq)(struct GpioCntlr *cntlr, uint16_t local);
int32_t (*enableIrq)(struct GpioCntlr *cntlr, uint16_t local);
int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local);
}
```
**Table 1** Callbacks for the members in the GpioMethod structure
<a name="table151341544111"></a>
<table><thead align="left"><tr id="row19514101504111"><th class="cellrowborder" align="center" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p451461513418"><a name="p451461513418"></a><a name="p451461513418"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p32641283426"><a name="p32641283426"></a><a name="p32641283426"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p55141515134111"><a name="p55141515134111"></a><a name="p55141515134111"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p5514171514114"><a name="p5514171514114"></a><a name="p5514171514114"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p155141215124113"><a name="p155141215124113"></a><a name="p155141215124113"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row195141715164110"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p145141015144110"><a name="p145141015144110"></a><a name="p145141015144110"></a>write</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p453215451206"><a name="p453215451206"></a><a name="p453215451206"></a><strong id="b1053114522014"><a name="b1053114522014"></a><a name="b1053114522014"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p116571249112015"><a name="p116571249112015"></a><a name="p116571249112015"></a><strong id="b8657144913202"><a name="b8657144913202"></a><a name="b8657144913202"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
<p id="p1351421512414"><a name="p1351421512414"></a><a name="p1351421512414"></a><strong id="b1861811201459"><a name="b1861811201459"></a><a name="b1861811201459"></a>val</strong>: input level value, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" align="left" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p8514715124111"><a name="p8514715124111"></a><a name="p8514715124111"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p14514161554118"><a name="p14514161554118"></a><a name="p14514161554118"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p155148151416"><a name="p155148151416"></a><a name="p155148151416"></a>Writes the level of a GPIO pin.</p>
</td>
</tr>
<tr id="row185141415174112"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1151520153413"><a name="p1151520153413"></a><a name="p1151520153413"></a>read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p139611135152114"><a name="p139611135152114"></a><a name="p139611135152114"></a><strong id="b4961435162120"><a name="b4961435162120"></a><a name="b4961435162120"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1451581512410"><a name="p1451581512410"></a><a name="p1451581512410"></a><strong id="b12610253913"><a name="b12610253913"></a><a name="b12610253913"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p19515415134113"><a name="p19515415134113"></a><a name="p19515415134113"></a><strong id="b5968229295"><a name="b5968229295"></a><a name="b5968229295"></a>val</strong>: pointer to the output level value, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1051591564115"><a name="p1051591564115"></a><a name="p1051591564115"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p185151715184112"><a name="p185151715184112"></a><a name="p185151715184112"></a>Reads the level of a GPIO pin.</p>
</td>
</tr>
<tr id="row4515111512414"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p125152152412"><a name="p125152152412"></a><a name="p125152152412"></a>setDir</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p5579168142212"><a name="p5579168142212"></a><a name="p5579168142212"></a><strong id="b357928112218"><a name="b357928112218"></a><a name="b357928112218"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1465781110227"><a name="p1465781110227"></a><a name="p1465781110227"></a><strong id="b4657711182217"><a name="b4657711182217"></a><a name="b4657711182217"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
<p id="p1551521584114"><a name="p1551521584114"></a><a name="p1551521584114"></a><strong id="b1172125431011"><a name="b1172125431011"></a><a name="b1172125431011"></a>dir</strong>: input pin direction, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1351541517413"><a name="p1351541517413"></a><a name="p1351541517413"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p251551515419"><a name="p251551515419"></a><a name="p251551515419"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1351501516419"><a name="p1351501516419"></a><a name="p1351501516419"></a>Sets the input or output direction for a GPIO pin.</p>
</td>
</tr>
<tr id="row10515161517417"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p135151015154114"><a name="p135151015154114"></a><a name="p135151015154114"></a>getDir</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p14901244112218"><a name="p14901244112218"></a><a name="p14901244112218"></a><strong id="b1689844182212"><a name="b1689844182212"></a><a name="b1689844182212"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1351531519411"><a name="p1351531519411"></a><a name="p1351531519411"></a><strong id="b171715420138"><a name="b171715420138"></a><a name="b171715420138"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p15515141554120"><a name="p15515141554120"></a><a name="p15515141554120"></a><strong id="b12246123210138"><a name="b12246123210138"></a><a name="b12246123210138"></a>dir</strong>: pointer to the output pin direction, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p651531574110"><a name="p651531574110"></a><a name="p651531574110"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1551620153418"><a name="p1551620153418"></a><a name="p1551620153418"></a>Obtains the input or output direction of a GPIO pin.</p>
</td>
</tr>
<tr id="row2051616153411"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p13516171517412"><a name="p13516171517412"></a><a name="p13516171517412"></a>setIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p139141552310"><a name="p139141552310"></a><a name="p139141552310"></a><strong id="b1791313562318"><a name="b1791313562318"></a><a name="b1791313562318"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p1939331118235"><a name="p1939331118235"></a><a name="p1939331118235"></a><strong id="b839319111238"><a name="b839319111238"></a><a name="b839319111238"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
<p id="p81051177235"><a name="p81051177235"></a><a name="p81051177235"></a><strong id="b6105141718231"><a name="b6105141718231"></a><a name="b6105141718231"></a>mode</strong>: triggering mode, which can be <strong id="b11105517102314"><a name="b11105517102314"></a><a name="b11105517102314"></a>edge</strong> or <strong id="b1210501711237"><a name="b1210501711237"></a><a name="b1210501711237"></a>level</strong>. The value is of the uint16_t type.</p>
<p id="p24421624172315"><a name="p24421624172315"></a><a name="p24421624172315"></a><strong id="b9442524112316"><a name="b9442524112316"></a><a name="b9442524112316"></a>func</strong>: function pointer to the interrupt service handler.</p>
<p id="p251619154417"><a name="p251619154417"></a><a name="p251619154417"></a><strong id="b33689285172"><a name="b33689285172"></a><a name="b33689285172"></a>arg</strong>: void pointer to the input parameters of the interrupt service handler.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1851631524118"><a name="p1851631524118"></a><a name="p1851631524118"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1551691512413"><a name="p1551691512413"></a><a name="p1551691512413"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p351615157411"><a name="p351615157411"></a><a name="p351615157411"></a>Sets an interrupt request (IRQ) for a GPIO pin.</p>
</td>
</tr>
<tr id="row135161157417"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p551631515418"><a name="p551631515418"></a><a name="p551631515418"></a>unsetIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p5931131516250"><a name="p5931131516250"></a><a name="p5931131516250"></a><strong id="b119311215162517"><a name="b119311215162517"></a><a name="b119311215162517"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p155164152415"><a name="p155164152415"></a><a name="p155164152415"></a><strong id="b1330123517188"><a name="b1330123517188"></a><a name="b1330123517188"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p8516161519416"><a name="p8516161519416"></a><a name="p8516161519416"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p4516415124119"><a name="p4516415124119"></a><a name="p4516415124119"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p451671594110"><a name="p451671594110"></a><a name="p451671594110"></a>Cancels the GPIO interrupt settings.</p>
</td>
</tr>
<tr id="row55161015134117"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p165161153415"><a name="p165161153415"></a><a name="p165161153415"></a>enableIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p87941124269"><a name="p87941124269"></a><a name="p87941124269"></a><strong id="b979421272616"><a name="b979421272616"></a><a name="b979421272616"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p85164158418"><a name="p85164158418"></a><a name="p85164158418"></a><strong id="b1046612112256"><a name="b1046612112256"></a><a name="b1046612112256"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p13517181584114"><a name="p13517181584114"></a><a name="p13517181584114"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1251711518412"><a name="p1251711518412"></a><a name="p1251711518412"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p65172015124114"><a name="p65172015124114"></a><a name="p65172015124114"></a>Enables an interrupt for a GPIO pin.</p>
</td>
</tr>
<tr id="row125171915154119"><td class="cellrowborder" align="center" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p155173157418"><a name="p155173157418"></a><a name="p155173157418"></a>disableIrq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p352101419274"><a name="p352101419274"></a><a name="p352101419274"></a><strong id="b052141472711"><a name="b052141472711"></a><a name="b052141472711"></a>cntlr</strong>: structure pointer to the GPIO controller at the core layer.</p>
<p id="p16517191544119"><a name="p16517191544119"></a><a name="p16517191544119"></a><strong id="b1173395802511"><a name="b1173395802511"></a><a name="b1173395802511"></a>local</strong>: GPIO port number, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1751751544113"><a name="p1751751544113"></a><a name="p1751751544113"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p11517515164117"><a name="p11517515164117"></a><a name="p11517515164117"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15517191534112"><a name="p15517191534112"></a><a name="p15517191534112"></a>Disables an interrupt for a GPIO pin.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section800425816103451"></a>
The following uses **gpio\_hi35xx.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 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.
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.
- GPIO driver entry reference
```
struct HdfDriverEntry g_gpioDriverEntry = {
.moduleVersion = 1,
.Bind = Pl061GpioBind, // Bind does not need to be implemented for GPIO. In this example, the implementation is empty. Vendors can add related operations as required.
.Init = Pl061GpioInit, // See the Init function.
.Release = Pl061GpioRelease, // See the Release function.
.moduleName = "hisi_pl061_driver",// (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 framework.
HDF_INIT(g_gpioDriverEntry);
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **gpio\_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 **GpioCntlr** members at the core layer.
In this example, there is only one GPIO controller. If there are multiple GPIO controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **gpio\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_gpio :: device {
device0 :: deviceNode {
policy = 0; // The value 0 indicates that no service needs to be published.
priority = 10; // Driver startup priority
permission = 0644; // Permission to create device nodes for the driver
moduleName = "hisi_pl061_driver"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
deviceMatchAttr = "hisilicon_hi35xx_pl061";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller information in gpio_config.hcs.
// The controller information must be consistent. Other controller information is also contained in the file.
}
}
}
}
}
```
- **gpio\_config.hcs** configuration reference
```
root {
platform {
gpio_config {
controller_0x120d0000 {
match_attr = "hisilicon_hi35xx_pl061"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
groupNum = 12; // (Mandatory) GPIO group index
bitNum = 8; // (Mandatory) Number of GPIO pins in each group
regBase = 0x120d0000;// (Mandatory) Physical base address
regStep = 0x1000; // (Mandatory) Register offset step
irqStart = 48; // (Mandatory) Start an IRQ.
irqShare = 0; // (Mandatory) Share the IRQ.
}
}
}
}
```
3. Initialize the **GpioCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **GpioMethod** \(used to call underlying functions of the driver\) in **GpioCntlr**, 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 **gpio\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also passed to the **GpioCntlr** object at the core layer.
```
struct Pl061GpioCntlr {
struct GpioCntlr cntlr;// (Mandatory) Control object of the core layer. For details about the member definitions, see the following description.
volatile unsigned char *regBase; // (Mandatory) Base address of the register
uint32_t phyBase; // (Mandatory) Physical base address
uint32_t regStep; // (Mandatory) Register offset step
uint32_t irqStart; // (Mandatory) Start an IRQ.
uint16_t groupNum; // (Mandatory) GPIO port number
uint16_t bitNum; // (Mandatory) GPIO port number
uint8_t irqShare; // (Mandatory) Share the IRQ.
struct Pl061GpioGroup *groups; // (Optional) Set based on the vendor's requirements.
};
struct Pl061GpioGroup {// Register address, interrupt number, interrupt function, and lock
volatile unsigned char *regBase;
unsigned int index;
unsigned int irq;
OsalIRQHandle irqFunc;
OsalSpinlock lock;
};
// GpioCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct GpioCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct GpioMethod *ops;
struct DListHead list;
OsalSpinlock spin;
uint16_t start;
uint16_t count;
struct GpioInfo *ginfos;
void *priv;
};
```
- Instantiate the callback function structure **GpioMethod** in **GpioCntlr**. Other members are initialized by using the **Init** function.
```
// The members of the GpioMethod structure are all callbacks. Vendors need to implement the corresponding functions according to [Table 1](#table151341544111).
static struct GpioMethod g_method = {
.request = NULL,
.release = NULL,
.write = Pl061GpioWrite, // Write pin settings.
.read = Pl061GpioRead, // Read pin settings.
.setDir = Pl061GpioSetDir, // Set the pin direction.
.getDir = Pl061GpioGetDir, // Obtain the pin direction.
.toIrq = NULL,
.setIrq = Pl061GpioSetIrq, // Set an interrupt for the pin. If this capability is not available, skip it.
.unsetIrq = Pl061GpioUnsetIrq, // Cancel the interrupt settings for the pin. If this capability is not available, skip it.
.enableIrq = Pl061GpioEnableIrq, // Enable an interrupt for the pin. If this capability is not available, skip it.
.disableIrq = Pl061GpioDisableIrq,// Disable the interrupt for the pin. If this capability is not available, skip it.
};
```
- Init 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** Init function description
<a name="table165981547354"></a>
<table><thead align="left"><tr id="row8599145423516"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p959995453515"><a name="p959995453515"></a><a name="p959995453515"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p185991854163519"><a name="p185991854163519"></a><a name="p185991854163519"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row13599195483515"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p125993545359"><a name="p125993545359"></a><a name="p125993545359"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p125991454153519"><a name="p125991454153519"></a><a name="p125991454153519"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row35997541354"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19600454153511"><a name="p19600454153511"></a><a name="p19600454153511"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1600145423514"><a name="p1600145423514"></a><a name="p1600145423514"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row9600155423514"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p146001546357"><a name="p146001546357"></a><a name="p146001546357"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p10600754133512"><a name="p10600754133512"></a><a name="p10600754133512"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row146001254143516"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p66007542357"><a name="p66007542357"></a><a name="p66007542357"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p2600135416357"><a name="p2600135416357"></a><a name="p2600135416357"></a>I/O error</p>
</td>
</tr>
<tr id="row36001544351"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p660095417357"><a name="p660095417357"></a><a name="p660095417357"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17600165411353"><a name="p17600165411353"></a><a name="p17600165411353"></a>Initialization successful</p>
</td>
</tr>
<tr id="row14600154103518"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p46001544356"><a name="p46001544356"></a><a name="p46001544356"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p160035415356"><a name="p160035415356"></a><a name="p160035415356"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **GpioCntlr**, calls the **GpioCntlrAdd** function at the core layer, and connects to the VFS \(optional\).
```
static int32_t Pl061GpioInit(struct HdfDeviceObject *device)
{
...
struct Pl061GpioCntlr *pl061 = &g_pl061;// Use static global variables to complete initialization.
//static struct Pl061GpioCntlr g_pl061 = {
// .groups = NULL,
// .groupNum = PL061_GROUP_MAX,
// .bitNum = PL061_BIT_MAX,
//};
ret = Pl061GpioReadDrs(pl061, device->property);// Use the attribute values read from the gpio_config.HCS file to initialize the members of the custom structure object.
...
pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);// Address mapping
...
ret = Pl061GpioInitCntlrMem(pl061); // Apply for memory.
...
pl061->cntlr.count = pl061->groupNum x pl061->bitNum;// (Mandatory) Calculate the number of pins.
pl061->cntlr.priv = (void *)device->property; // (Mandatory) Store device attributes.
pl061->cntlr.ops = &g_method; // (Mandatory) Connect to the GpioMethod instance.
pl061->cntlr.device = device; // (Mandatory) Enable conversion between HdfDeviceObject and GpioCntlr.
ret = GpioCntlrAdd(&pl061->cntlr); // (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.
...
Pl061GpioDebugCntlr(pl061);
#ifdef PL061_GPIO_USER_SUPPORT // (Optional) Access the user-level virtual file system if supported.
if (GpioAddVfs(pl061->bitNum) != HDF_SUCCESS) {
HDF_LOGE("%s: add vfs fail!", __func__);
}
#endif
...
}
```
- 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 framework 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.
```
static void Pl061GpioRelease(struct HdfDeviceObject *device)
{
struct GpioCntlr *cntlr = NULL;
struct Pl061GpioCntlr *pl061 = NULL;
...
cntlr = GpioCntlrFromDevice(device);// (Mandatory) Obtain the control object of the core layer through forced conversion.
//return (device == NULL) ? NULL : (struct GpioCntlr *)device->service;
...
#ifdef PL061_GPIO_USER_SUPPORT
GpioRemoveVfs();// Perform operations reverse to GpioAddVfs in Init.
#endif
GpioCntlrRemove(cntlr); // (Mandatory) Remove the device information and services from the core layer.
pl061 = ToPl061GpioCntlr(cntlr); //return (struct Pl061GpioCntlr *)cntlr;
Pl061GpioRleaseCntlrMem(pl061); // (Mandatory) Release the lock and memory.
OsalIoUnmap((void *)pl061->regBase);// (Mandatory) Remove the address mapping.
pl061->regBase = NULL;
}
```
# I2C<a name="EN-US_TOPIC_0000001052778273"></a>
# I2C<a name="EN-US_TOPIC_0000001206171515"></a>
- [Overview](#section5361140416)
- [Available APIs](#section459052019177)
- [Available APIs](#section545869122317)
- [Usage Guidelines](#section1695201514281)
- [How to Use](#section1338373417288)
- [Opening an I2C Controller](#section13751110132914)
......@@ -25,10 +24,10 @@
- I2C message transfer: custom transfer by using a message array
**Figure 1** Physical connection diagram for I2C<a name="fig1135561232714"></a>
![](figure/physical-connection-diagram-for-i2c.png "physical-connection-diagram-for-i2c")
![](figures/physical-connection-diagram-for-i2c.png "physical-connection-diagram-for-i2c")
### Available APIs<a name="section459052019177"></a>
## Available APIs<a name="section545869122317"></a>
**Table 1** APIs available for the I2C driver
......@@ -70,12 +69,10 @@
### How to Use<a name="section1338373417288"></a>
[Figure 2](#fig166181128151112) illustrates the process of an I2C device.
**Figure 2** Process of using an I2C device<a name="fig166181128151112"></a>
[Figure 2](#fig183017194234) illustrates the process of an I2C device.
![](figure/en-us_image_0000001123509750.png)
**Figure 2** Process of using an I2C device<a name="fig183017194234"></a>
![](figures/process-of-using-an-i2c-device.png "process-of-using-an-i2c-device")
### Opening an I2C Controller<a name="section13751110132914"></a>
......@@ -405,7 +402,7 @@ static int32_t TestCaseI2c(void)
}
OsalMSleep(10);
/* Continuously read 7-byte data from register 0xDO of TP-IC. */
/* Continuously read 7-byte data from register 0xD5 of TP-IC. */
ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret);
......
# I2C<a name="EN-US_TOPIC_0000001153579420"></a>
- [Overview](#section2040078630114257)
- [How to Develop](#section1085786591114257)
- [I2cMethod and I2cLockMethod](#section1683458184518)
- [Development Example](#section1773332551114257)
## Overview<a name="section2040078630114257"></a>
The Inter-Integrated Circuit \(I2C\) bus is a simple and bidirectional two-wire synchronous serial bus developed by Philips. In the HDF framework, the I2C module uses the unified service mode for API adaptation. In this mode, a device service is used as the I2C 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 I2C module 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.
**Figure 1** Unified service mode<a name="fig17640124912440"></a>
![](figures/unified-service-mode-8.png "unified-service-mode-8")
## How to Develop<a name="section1085786591114257"></a>
The I2C 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **i2c\_config.hcs** file.
3. Instantiate the I2C controller object.
- Initialize **I2cCntlr**.
- Instantiate **I2cMethod** and **I2cLockMethod** in **I2cCntlr**.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [I2cMethod and I2cLockMethod](#section1683458184518) and [Table 1](#table10549174014611).
4. Debug the driver.
- \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted.
### I2cMethod and I2cLockMethod<a name="section1683458184518"></a>
```
struct I2cMethod {
int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
};
struct I2cLockMethod {// Lock mechanism operation structure
int32_t (*lock)(struct I2cCntlr *cntlr); // Add a lock.
void (*unlock)(struct I2cCntlr *cntlr); // Release the lock.
};
```
**Table 1** Callbacks for the members in the I2cMethod structure
<a name="table10549174014611"></a>
<table><thead align="left"><tr id="row17550114013460"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p155014403467"><a name="p155014403467"></a><a name="p155014403467"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p165507404466"><a name="p165507404466"></a><a name="p165507404466"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p8550194015467"><a name="p8550194015467"></a><a name="p8550194015467"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p65501540184618"><a name="p65501540184618"></a><a name="p65501540184618"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p185501740194610"><a name="p185501740194610"></a><a name="p185501740194610"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row75509402460"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p0550104084617"><a name="p0550104084617"></a><a name="p0550104084617"></a>transfer</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p9551164011468"><a name="p9551164011468"></a><a name="p9551164011468"></a><strong id="b1413775771219"><a name="b1413775771219"></a><a name="b1413775771219"></a>cntlr</strong>: structure pointer to the I2C controller at the core layer. <strong id="b13955019171313"><a name="b13955019171313"></a><a name="b13955019171313"></a>msgs</strong>: structure pointer to the user message. <strong id="b4678857181319"><a name="b4678857181319"></a><a name="b4678857181319"></a>count</strong>: number of messages, which is of the uint16_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p6551140124620"><a name="p6551140124620"></a><a name="p6551140124620"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p555144084619"><a name="p555144084619"></a><a name="p555144084619"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p8551174044612"><a name="p8551174044612"></a><a name="p8551174044612"></a>Transfers user messages.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1773332551114257"></a>
The following uses **i2c\_hi35xx.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 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.
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.
- I2C driver entry reference
Many devices may be connected to the I2C module. Therefore, in the HDF framework, a manager object is created for the I2C, and a manager service is launched to handle external access requests in a unified manner. When a user wants to open a device, the user obtains the manager service first. Then, the manager service locates the target device based on the parameters specified by the user.
The driver of the I2C 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 **I2cCntlrAdd** function of the core layer must be called to implement the corresponding features.
```
struct HdfDriverEntry g_i2cDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxI2cInit,
.Release = Hi35xxI2cRelease,
.moduleName = "hi35xx_i2c_driver",// (Mandatory) The value must be the same as that in the config.hcs file.
};
HDF_INIT(g_i2cDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework.
// Driver entry of the i2c_core.c manager service at the core layer
struct HdfDriverEntry g_i2cManagerEntry = {
.moduleVersion = 1,
.Bind = I2cManagerBind,
.Init = I2cManagerInit,
.Release = I2cManagerRelease,
.moduleName = "HDF_PLATFORM_I2C_MANAGER",// This parameter corresponds to device0 in the device_info file.
};
HDF_INIT(g_i2cManagerEntry);
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the device attributes in the **i2c\_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 **I2cCntlr** members at the core layer.
In the unified service mode, the first device node in the **device\_info** file must be the I2C manager. [Table 2](#table96651915911) lists settings of its parameters.
**Table 2** Settings of the I2C manager
<a name="table96651915911"></a>
<table><thead align="left"><tr id="row96618194915"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1066119790"><a name="p1066119790"></a><a name="p1066119790"></a>Member</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p8674191494"><a name="p8674191494"></a><a name="p8674191494"></a>Value</p>
</th>
</tr>
</thead>
<tbody><tr id="row767111916914"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p46714196920"><a name="p46714196920"></a><a name="p46714196920"></a>moduleName</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p36717191292"><a name="p36717191292"></a><a name="p36717191292"></a>It has a fixed value of <strong id="b1343012314357"><a name="b1343012314357"></a><a name="b1343012314357"></a>HDF_PLATFORM_I2C_MANAGER</strong>.</p>
</td>
</tr>
<tr id="row16671119392"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p11671019699"><a name="p11671019699"></a><a name="p11671019699"></a>serviceName</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p86716195912"><a name="p86716195912"></a><a name="p86716195912"></a>It has a fixed value of <strong id="b107651238143515"><a name="b107651238143515"></a><a name="b107651238143515"></a>HDF_PLATFORM_I2C_MANAGER</strong>.</p>
</td>
</tr>
<tr id="row17673191911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p5673191898"><a name="p5673191898"></a><a name="p5673191898"></a>policy</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p18677191699"><a name="p18677191699"></a><a name="p18677191699"></a>The value can be <strong id="b13997735183718"><a name="b13997735183718"></a><a name="b13997735183718"></a>1</strong> or <strong id="b165591038103717"><a name="b165591038103717"></a><a name="b165591038103717"></a>2</strong>, depending on whether it is visible to the user mode.</p>
</td>
</tr>
<tr id="row8675191894"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12677191913"><a name="p12677191913"></a><a name="p12677191913"></a>deviceMatchAttr</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1567171918915"><a name="p1567171918915"></a><a name="p1567171918915"></a>This parameter is not used.</p>
</td>
</tr>
</tbody>
</table>
Configure I2C controller information from the second node. This node specifies a type of I2C controllers rather than an I2C controller. The **busID** and **reg\_pbase** parameters distinguish controllers, which can be seen in the **i2c\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
device_i2c :: device {
device0 :: deviceNode {
policy = 2;
priority = 50;
permission = 0644;
moduleName = "HDF_PLATFORM_I2C_MANAGER";
serviceName = "HDF_PLATFORM_I2C_MANAGER";
deviceMatchAttr = "hdf_platform_i2c_manager";
}
device1 :: deviceNode {
policy = 0; // The value 0 indicates that no service needs to be published.
priority = 55; // Driver startup priority
permission = 0644; // Permission for the driver to create a device node
moduleName = "hi35xx_i2c_driver"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HI35XX_I2C_DRIVER"; // (Mandatory) Unique name of the service published by the driver
deviceMatchAttr = "hisilicon_hi35xx_i2c";// (Mandatory) Used to configure the private data of the controller. The value must be the same as the controller in i2c_config.hcs.
} // The specific controller information is in i2c_config.hcs.
}
}
}
}
```
- **i2c\_config.hcs** configuration reference
```
root {
platform {
i2c_config {
match_attr = "hisilicon_hi35xx_i2c";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
template i2c_controller { // Template configuration. In the template, you can configure the common parameters shared by service nodes.
bus = 0; // (Mandatory) I2C ID
reg_pbase = 0x120b0000; // (Mandatory) Physical base address
reg_size = 0xd1; // (Mandatory) Register bit width
irq = 0; // (Optional) Configured based on the vendor's requirements.
freq = 400000; // (Optional) Configured based on the vendor's requirements.
clk = 50000000; // (Optional) Configured based on the vendor's requirements.
}
controller_0x120b0000 :: i2c_controller {
bus = 0;
}
controller_0x120b1000 :: i2c_controller {
bus = 1;
reg_pbase = 0x120b1000;
}
...
}
}
}
```
3. Initialize the **I2cCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **I2cMethod** \(used to call underlying functions of the driver\) in **I2cCntlr**, 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 **i2c\_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 **I2cCntlr** object at the core layer.
```
// Vendor custom function structure
struct Hi35xxI2cCntlr {
struct I2cCntlr cntlr; // (Mandatory) Control object of the core layer. For details, see the following description.
OsalSpinlock spin; // (Mandatory) The vendor needs to implement lock and unlock for I2C operation functions based on this variable.
volatile unsigned char *regBase; // (Mandatory) Base address of the register
uint16_t regSize; // (mandatory) Bit width of the register
int16_t bus; // (Mandatory) The value can be read from the i2c_config.hcs file.
uint32_t clk; // (Optional) Customized by the vendor.
uint32_t freq; // (Optional) Customized by the vendor.
uint32_t irq; // (Optional) Customized by the vendor.
uint32_t regBasePhy; // (Mandatory) Physical base address of the register
};
// I2cCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct I2cCntlr {
struct OsalMutex lock;
void *owner;
int16_t busId;
void *priv;
const struct I2cMethod *ops;
const struct I2cLockMethod *lockOps;
};
```
- Instantiate the member callback function structure **I2cMethod** in **I2cCntlr** and the lock callback function structure **I2cLockMethod**. Other members are initialized by using the **Init** function.
```
// Example in i2c_hi35xx.c
static const struct I2cMethod g_method = {
.transfer = Hi35xxI2cTransfer,
};
static const struct I2cLockMethod g_lockOps = {
.lock = Hi35xxI2cLock, // Lock function
.unlock = Hi35xxI2cUnlock,// Unlock function
};
```
- Init 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 3** Input parameters and return values of the Init function
<a name="table1743073181511"></a>
<table><thead align="left"><tr id="row443033171513"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p34306341517"><a name="p34306341517"></a><a name="p34306341517"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p1243123101510"><a name="p1243123101510"></a><a name="p1243123101510"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row5431638151"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1043114319156"><a name="p1043114319156"></a><a name="p1043114319156"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p343173101513"><a name="p343173101513"></a><a name="p343173101513"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row1243143181516"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1443118317154"><a name="p1443118317154"></a><a name="p1443118317154"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p343113341515"><a name="p343113341515"></a><a name="p343113341515"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1943115391516"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1843143171511"><a name="p1843143171511"></a><a name="p1843143171511"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p943114391515"><a name="p943114391515"></a><a name="p943114391515"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row1443183101514"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p54311031157"><a name="p54311031157"></a><a name="p54311031157"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p74315311158"><a name="p74315311158"></a><a name="p74315311158"></a>I/O error</p>
</td>
</tr>
<tr id="row3431437158"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8432332158"><a name="p8432332158"></a><a name="p8432332158"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p104329391519"><a name="p104329391519"></a><a name="p104329391519"></a>Transmission successful</p>
</td>
</tr>
<tr id="row34321136152"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p184325391517"><a name="p184325391517"></a><a name="p184325391517"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1343220319154"><a name="p1343220319154"></a><a name="p1343220319154"></a>Transmission failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **I2cCntlr**, calls the **I2cCntlrAdd** function at the core layer, and connects to the VFS \(optional\).
```
static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device)
{
...
// Traverse and parse all nodes in i2c_config.hcs and call Hi35xxI2cParseAndInit to initialize the devices separately.
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
ret = Hi35xxI2cParseAndInit(device, childNode);// For details about the function definition, see the following description.
...
}
...
}
static int32_t Hi35xxI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
struct Hi35xxI2cCntlr *hi35xx = NULL;
...
hi35xx = (struct Hi35xxI2cCntlr *)OsalMemCalloc(sizeof(*hi35xx)); // Apply for memory.
...
hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize); // Address mapping
...
Hi35xxI2cCntlrInit(hi35xx); // (Mandatory) Initialize the I2C device.
hi35xx->cntlr.priv = (void *)node; // (Mandatory) Store device attributes.
hi35xx->cntlr.busId = hi35xx->bus; // (Mandatory) Initialize busId in I2cCntlr.
hi35xx->cntlr.ops = &g_method; // (Mandatory) Connect to the I2cMethod instance.
hi35xx->cntlr.lockOps = &g_lockOps; // (Mandatory) Connect to the I2cLockMethod instance.
(void)OsalSpinInit(&hi35xx->spin); // (Mandatory) Initialize the lock.
ret = I2cCntlrAdd(&hi35xx->cntlr); // (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.
...
#ifdef USER_VFS_SUPPORT
(void)I2cAddVfsById(hi35xx->cntlr.busId);// (Optional) Connect the driver to the user-level virtual file system supported.
#endif
return HDF_SUCCESS;
__ERR__: // If the operation fails, execute the initialization function reversely.
if (hi35xx != NULL) {
if (hi35xx->regBase != NULL) {
OsalIoUnmap((void *)hi35xx->regBase);
hi35xx->regBase = NULL;
}
OsalMemFree(hi35xx);
hi35xx = NULL;
}
return ret;
}
```
- 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 framework fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
```
static void Hi35xxI2cRelease(struct HdfDeviceObject *device)
{
...
// Release each node separately, like Hi35xxI2cInit.
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
Hi35xxI2cRemoveByNode(childNode);// The function definition is as follows:
}
}
static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node)
{
...
// (Mandatory) Call the I2cCntlrGet function obtain the I2cCntlr object based on busid of the device, and call the I2cCntlrRemove function to release the I2cCntlr object.
cntlr = I2cCntlrGet(bus);
if (cntlr != NULL && cntlr->priv == node) {
...
I2cCntlrRemove(cntlr);
// (Mandatory) Remove the address mapping and release the lock and memory.
hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
OsalIoUnmap((void *)hi35xx->regBase);
(void)OsalSpinDestroy(&hi35xx->spin);
OsalMemFree(hi35xx);
}
return;
}
```
# MIPI DSI<a name="EN-US_TOPIC_0000001062724343"></a>
# MIPI DSI<a name="EN-US_TOPIC_0000001160971534"></a>
- [Overview](#section16806142183217)
- [Available APIs](#section129611916132011)
- [Available APIs](#section12720125432316)
- [Usage Guidelines](#section037231715335)
- [How to Use](#section49299119344)
- [Obtains a MIPI DSI device handle.](#section5126155683811)
......@@ -20,10 +19,10 @@
- [Figure 1](#fig1122611461203) shows a simplified DSI interface. Conceptually, a DSI-compliant interface has the same features as interfaces complying with DBI-2 and DPI-2 standards. It sends pixels or commands to a peripheral and can read status or pixel information from the peripheral. The main difference is that the DSI serializes all pixel data, commands, and events that, in traditional interfaces, are conveyed to and from the peripheral on a parallel data bus with additional control signals.
**Figure 1** DSI transmitting and receiving interface<a name="fig1122611461203"></a>
![](figure/dsi-transmitting-and-receiving-interface.png "dsi-transmitting-and-receiving-interface")
![](figures/dsi-transmitting-and-receiving-interface.png "dsi-transmitting-and-receiving-interface")
### Available APIs<a name="section129611916132011"></a>
## Available APIs<a name="section12720125432316"></a>
**Table 1** APIs for MIPI DSI
......@@ -94,12 +93,10 @@
### How to Use<a name="section49299119344"></a>
[Figure 2](#fig99821771782) shows the process of using a MIPI DSI device.
**Figure 2** Process of using a MIPI DSI device<a name="fig99821771782"></a>
[Figure 2](#fig129103491241) shows the process of using a MIPI DSI device.
![](figure/en-us_image_0000001123514210.png)
**Figure 2** Process of using a MIPI DSI device<a name="fig129103491241"></a>
![](figures/process-of-using-a-mipi-dsi-device.png "process-of-using-a-mipi-dsi-device")
### Obtains a MIPI DSI device handle.<a name="section5126155683811"></a>
......
# MIPI-DSI<a name="EN-US_TOPIC_0000001199825369"></a>
- [Overview](#section1266787503161538)
- [How to Develop](#section545182932161538)
- [MipiDsiCntlrMethod](#section10711202141617)
- [Development Example](#section1167576616161538)
## Overview<a name="section1266787503161538"></a>
The Display Serial Interface \(DSI\) is a specification developed by the Mobile Industry Processor Interface \(MIPI\) Alliance to reduce the cost of display controllers in mobile devices. In the HDF framework, the MIPI-DSI module uses the service-free mode for API adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS system that does not distinguish the user mode and the kernel mode. In the service-free mode, **DevHandle** \(a void pointer\) directly points to the kernel-mode address of the device object.
**Figure 1** Service-free mode<a name="fig207610236189"></a>
![](figures/service-free-mode-9.png "service-free-mode-9")
## How to Develop<a name="section545182932161538"></a>
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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **mipidsi\_config.hcs** file.
3. Instantiate the MIPI-DSI controller object.
- Initialize **MipiDsiCntlr**.
- Instantiate **MipiDsiCntlrMethod** in the **MipiDsiCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [MipiDsiCntlrMethod](#section10711202141617) and [Table 1](#table218771071713).
4. Debug the driver.
- \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether data is successfully transmitted.
### MipiDsiCntlrMethod<a name="section10711202141617"></a>
```
struct MipiDsiCntlrMethod {// Member functions of the core layer structure
int32_t (*setCntlrCfg)(struct MipiDsiCntlr *cntlr);
int32_t (*setCmd)(struct MipiDsiCntlr *cntlr, struct DsiCmdDesc *cmd);
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 consumption mode.
void (*exitUlps)(struct MipiDsiCntlr *cntlr); // (Optional) Exit the ultra-low power consumption mode.
int32_t (*powerControl)(struct MipiDsiCntlr *cntlr, uint8_t enable);// (Optional) Enable or disable power control.
int32_t (*attach)(struct MipiDsiCntlr *cntlr);// (Optional) Connect a DSI device to the host.
};
```
**Table 1** Callbacks for the members in the MipiDsiCntlrMethod structure
<a name="table218771071713"></a>
<table><thead align="left"><tr id="row1188121012177"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p118851010174"><a name="p118851010174"></a><a name="p118851010174"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p121881109177"><a name="p121881109177"></a><a name="p121881109177"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p1818831011176"><a name="p1818831011176"></a><a name="p1818831011176"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p1418815106171"><a name="p1418815106171"></a><a name="p1418815106171"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p10949971916"><a name="p10949971916"></a><a name="p10949971916"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row318920102175"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p01891103178"><a name="p01891103178"></a><a name="p01891103178"></a>setCntlrCfg</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1518931041716"><a name="p1518931041716"></a><a name="p1518931041716"></a><strong id="b14872821599"><a name="b14872821599"></a><a name="b14872821599"></a>cntlr</strong>: structure pointer to the MIPI-DSI controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p51893103174"><a name="p51893103174"></a><a name="p51893103174"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p15189111019176"><a name="p15189111019176"></a><a name="p15189111019176"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p918911010174"><a name="p918911010174"></a><a name="p918911010174"></a>Sets controller parameters.</p>
</td>
</tr>
<tr id="row10189210151713"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p518991017171"><a name="p518991017171"></a><a name="p518991017171"></a>setCmd</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p177917412215"><a name="p177917412215"></a><a name="p177917412215"></a><strong id="b4791144113213"><a name="b4791144113213"></a><a name="b4791144113213"></a>cntlr</strong>: structure pointer to the MIPI-DSI controller. </p>
<p id="p12189131018174"><a name="p12189131018174"></a><a name="p12189131018174"></a><strong id="b192414338012"><a name="b192414338012"></a><a name="b192414338012"></a>cmd</strong>: structure pointer to the input instruction.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p191891210111710"><a name="p191891210111710"></a><a name="p191891210111710"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p15189201019178"><a name="p15189201019178"></a><a name="p15189201019178"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15190110141710"><a name="p15190110141710"></a><a name="p15190110141710"></a>Sends instructions to a display device.</p>
</td>
</tr>
<tr id="row2190161061714"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p111901810181715"><a name="p111901810181715"></a><a name="p111901810181715"></a>getCmd</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p121902101179"><a name="p121902101179"></a><a name="p121902101179"></a><strong id="b516432716114"><a name="b516432716114"></a><a name="b516432716114"></a>cntlr</strong>: structure pointer to the MIPI-DSI controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1519018101171"><a name="p1519018101171"></a><a name="p1519018101171"></a>cmd: structure pointer to the instruction to output.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p101904107171"><a name="p101904107171"></a><a name="p101904107171"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p519061031710"><a name="p519061031710"></a><a name="p519061031710"></a>Reads instructions from the display device.</p>
</td>
</tr>
<tr id="row1919071016171"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p16190131051710"><a name="p16190131051710"></a><a name="p16190131051710"></a>toHs</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p151906102178"><a name="p151906102178"></a><a name="p151906102178"></a><strong id="b159559351014"><a name="b159559351014"></a><a name="b159559351014"></a>cntlr</strong>: structure pointer to the MIPI-DSI controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p10190181031720"><a name="p10190181031720"></a><a name="p10190181031720"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p019015102174"><a name="p019015102174"></a><a name="p019015102174"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p2190310101715"><a name="p2190310101715"></a><a name="p2190310101715"></a>Sets the high-speed mode.</p>
</td>
</tr>
<tr id="row01911510161718"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p10191141081717"><a name="p10191141081717"></a><a name="p10191141081717"></a>toLp</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p819121011714"><a name="p819121011714"></a><a name="p819121011714"></a><strong id="b189629351219"><a name="b189629351219"></a><a name="b189629351219"></a>cntlr</strong>: structure pointer to the MIPI-DSI controller.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p3191510171717"><a name="p3191510171717"></a><a name="p3191510171717"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p8191110151714"><a name="p8191110151714"></a><a name="p8191110151714"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1919121091712"><a name="p1919121091712"></a><a name="p1919121091712"></a>Sets the low-power mode.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1167576616161538"></a>
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. Generally, you need to 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, you need to add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the **mipidsi\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mipi_dsi:: device {
device0 :: deviceNode {
policy = 0;
priority = 150;
permission = 0644;
moduleName = "HDF_MIPI_TX"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HDF_MIPI_TX";// (Mandatory) Unique name of the service published by the driver
}
}
}
}
}
```
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 of the **HdfDriverEntry** structure are filled by the vendors' operation functions. 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.
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.
- MIPI-DSI driver entry reference
```
struct HdfDriverEntry g_mipiTxDriverEntry = {
.moduleVersion = 1,
.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.
};
HDF_INIT(g_mipiTxDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework.
```
3. Initialize the **MipiDsiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MipiDsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiDsiCntlr**, 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 **config** file are used to initialize the structure members. 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; // mbps
unsigned int pixelClk; // KHz
} ComboDevCfgTag;
// MipiDsiCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct MipiDsiCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
unsigned int devNo; // Device number
struct MipiCfg cfg;
struct MipiDsiCntlrMethod *ops;
struct OsalMutex lock;
void *priv;
};
```
- Instantiate the callback function structure **MipiDsiCntlrMethod** in **MipiDsiCntlr**. Other members are initialized by using the **Init** function.
```
static struct MipiDsiCntlrMethod g_method = {
.setCntlrCfg = Hi35xxSetCntlrCfg,
.setCmd = Hi35xxSetCmd,
.getCmd = Hi35xxGetCmd,
.toHs = Hi35xxToHs,
.toLp = Hi35xxToLp,
};
```
- Init 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.\)
<a name="table344041707161538"></a>
<table><thead align="left"><tr id="row1205250994161538"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1646623665161538p0"><a name="entry1646623665161538p0"></a><a name="entry1646623665161538p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry36551796161538p0"><a name="entry36551796161538p0"></a><a name="entry36551796161538p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1245832689161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry635453137161538p0"><a name="entry635453137161538p0"></a><a name="entry635453137161538p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1681554112161538p0"><a name="entry1681554112161538p0"></a><a name="entry1681554112161538p0"></a>Invalid object</p>
</td>
</tr>
<tr id="row86233502161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry2128705324161538p0"><a name="entry2128705324161538p0"></a><a name="entry2128705324161538p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1664050443161538p0"><a name="entry1664050443161538p0"></a><a name="entry1664050443161538p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row230078441161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry325107899161538p0"><a name="entry325107899161538p0"></a><a name="entry325107899161538p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry754791216161538p0"><a name="entry754791216161538p0"></a><a name="entry754791216161538p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row20758403161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1970333605161538p0"><a name="entry1970333605161538p0"></a><a name="entry1970333605161538p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1122658595161538p0"><a name="entry1122658595161538p0"></a><a name="entry1122658595161538p0"></a>I/O error</p>
</td>
</tr>
<tr id="row1425117417161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1844298129161538p0"><a name="entry1844298129161538p0"></a><a name="entry1844298129161538p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry712326009161538p0"><a name="entry712326009161538p0"></a><a name="entry712326009161538p0"></a>Operation successful</p>
</td>
</tr>
<tr id="row1899574933161538"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1964112434161538p0"><a name="entry1964112434161538p0"></a><a name="entry1964112434161538p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1481231483161538p0"><a name="entry1481231483161538p0"></a><a name="entry1481231483161538p0"></a>Operation failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Connects to 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;// Connect to 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, core layer 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; // Enable conversion between HdfDeviceObject and MipiDsiHandle.
device->service = &(cntlr->service); // Enable conversion between HdfDeviceObject and MipiDsiHandle.
cntlr->priv = NULL;
...
return HDF_SUCCESS;
}
...
return HDF_FAILURE;
}
```
- 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 framework 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.
```
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__);
}
```
# MMC<a name="EN-US_TOPIC_0000001153669000"></a>
- [Overview](#section1846388309162704)
- [How to Develop](#section1617495117162704)
- [MmcCntlrOps](#section6203107192915)
- [Development Example](#section1220893490162704)
## Overview<a name="section1846388309162704"></a>
In the Hardware Driver Foundation \(HDF\) framework, the MultiMedia Card \(MMC\) 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.
**Figure 1** Independent service mode<a name="fig19517114132810"></a>
![](figures/independent-service-mode.png "independent-service-mode")
## How to Develop<a name="section1617495117162704"></a>
The MMC 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **mmc\_config.hcs** file.
3. Instantiate the MMC controller object.
- Initialize **MmcCntlr**.
- Instantiate **MmcCntlrOps** in the **MmcCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [MmcCntlrOps](#section6203107192915) and [Table 1](#table99129433019).
4. Debug the driver.
- \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the mount operation and whether the device starts successfully.
### MmcCntlrOps<a name="section6203107192915"></a>
```
struct MmcCntlrOps {
int32_t (*request)(struct MmcCntlr *cntlr, struct MmcCmd *cmd);
int32_t (*setClock)(struct MmcCntlr *cntlr, uint32_t clock);
int32_t (*setPowerMode)(struct MmcCntlr *cntlr, enum MmcPowerMode mode);
int32_t (*setBusWidth)(struct MmcCntlr *cntlr, enum MmcBusWidth width);
int32_t (*setBusTiming)(struct MmcCntlr *cntlr, enum MmcBusTiming timing);
int32_t (*setSdioIrq)(struct MmcCntlr *cntlr, bool enable);
int32_t (*hardwareReset)(struct MmcCntlr *cntlr);
int32_t (*systemInit)(struct MmcCntlr *cntlr);
int32_t (*setEnhanceSrobe)(struct MmcCntlr *cntlr, bool enable);
int32_t (*switchVoltage)(struct MmcCntlr *cntlr, enum MmcVolt volt);
bool (*devReadOnly)(struct MmcCntlr *cntlr);
bool (*devPluged)(struct MmcCntlr *cntlr);
bool (*devBusy)(struct MmcCntlr *cntlr);
int32_t (*tune)(struct MmcCntlr *cntlr, uint32_t cmdCode);
int32_t (*rescanSdioDev)(struct MmcCntlr *cntlr);
};
```
**Table 1** Callbacks for the members in the MmcCntlrOps structure
<a name="table99129433019"></a>
<table><thead align="left"><tr id="row1891214163012"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p79129483017"><a name="p79129483017"></a><a name="p79129483017"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p1591213403019"><a name="p1591213403019"></a><a name="p1591213403019"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p491312483012"><a name="p491312483012"></a><a name="p491312483012"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p8913144203017"><a name="p8913144203017"></a><a name="p8913144203017"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row4913844307"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p17913149309"><a name="p17913149309"></a><a name="p17913149309"></a>doRequest</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p359655512340"><a name="p359655512340"></a><a name="p359655512340"></a><strong id="b1596155533411"><a name="b1596155533411"></a><a name="b1596155533411"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p159131449308"><a name="p159131449308"></a><a name="p159131449308"></a><strong id="b71781053113715"><a name="b71781053113715"></a><a name="b71781053113715"></a>cmd</strong>: structure pointer to the input command.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1291519413308"><a name="p1291519413308"></a><a name="p1291519413308"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p3915048309"><a name="p3915048309"></a><a name="p3915048309"></a>Processes the request.</p>
</td>
</tr>
<tr id="row17915124113014"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p69152416307"><a name="p69152416307"></a><a name="p69152416307"></a>setClock</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p12397758163416"><a name="p12397758163416"></a><a name="p12397758163416"></a><strong id="b2397155816345"><a name="b2397155816345"></a><a name="b2397155816345"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p119153413013"><a name="p119153413013"></a><a name="p119153413013"></a><strong id="b13651101617393"><a name="b13651101617393"></a><a name="b13651101617393"></a>clock</strong>: input clock value.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p79153417302"><a name="p79153417302"></a><a name="p79153417302"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1291614183010"><a name="p1291614183010"></a><a name="p1291614183010"></a>Sets the clock frequency.</p>
</td>
</tr>
<tr id="row19168433011"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1391614416305"><a name="p1391614416305"></a><a name="p1391614416305"></a>setPowerMode</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p349710303139"><a name="p349710303139"></a><a name="p349710303139"></a><strong id="b749713013132"><a name="b749713013132"></a><a name="b749713013132"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p99161341305"><a name="p99161341305"></a><a name="p99161341305"></a><strong id="b1355614134405"><a name="b1355614134405"></a><a name="b1355614134405"></a>mode</strong>: power consumption mode. It is an enumerated value (see MmcPowerMode).</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1091674183020"><a name="p1091674183020"></a><a name="p1091674183020"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1191617420307"><a name="p1191617420307"></a><a name="p1191617420307"></a>Sets the power consumption mode.</p>
</td>
</tr>
<tr id="row291620463018"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p291612453018"><a name="p291612453018"></a><a name="p291612453018"></a>setBusWidth</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p52591598350"><a name="p52591598350"></a><a name="p52591598350"></a><strong id="b225999203512"><a name="b225999203512"></a><a name="b225999203512"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p11916245309"><a name="p11916245309"></a><a name="p11916245309"></a><strong id="b24742024134111"><a name="b24742024134111"></a><a name="b24742024134111"></a>width</strong>: bus width. It is an enumerated value (see MmcBusWidth).</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1491610415305"><a name="p1491610415305"></a><a name="p1491610415305"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p19916147304"><a name="p19916147304"></a><a name="p19916147304"></a>Sets the bus width.</p>
</td>
</tr>
<tr id="row1916742301"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p3916104143014"><a name="p3916104143014"></a><a name="p3916104143014"></a>setBusTiming</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p109861912123517"><a name="p109861912123517"></a><a name="p109861912123517"></a><strong id="b39864125357"><a name="b39864125357"></a><a name="b39864125357"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p591710419302"><a name="p591710419302"></a><a name="p591710419302"></a><strong id="b1067164920426"><a name="b1067164920426"></a><a name="b1067164920426"></a>timing</strong>: bus timing. It is an enumerated value (see MmcBusTiming).</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p14917154123017"><a name="p14917154123017"></a><a name="p14917154123017"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1991814443016"><a name="p1991814443016"></a><a name="p1991814443016"></a>Sets the bus timing.</p>
</td>
</tr>
<tr id="row199186423012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p991810414305"><a name="p991810414305"></a><a name="p991810414305"></a>setSdioIrq</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p207324169351"><a name="p207324169351"></a><a name="p207324169351"></a><strong id="b11731716183510"><a name="b11731716183510"></a><a name="b11731716183510"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p16918844305"><a name="p16918844305"></a><a name="p16918844305"></a><strong id="b49304428454"><a name="b49304428454"></a><a name="b49304428454"></a>enable</strong>: specifies whether to enable interrupt.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p17918204193011"><a name="p17918204193011"></a><a name="p17918204193011"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1191813416305"><a name="p1191813416305"></a><a name="p1191813416305"></a>Enables or disables Secure Digital Input Output (SDIO) interrupt.</p>
</td>
</tr>
<tr id="row139181453012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p491874193011"><a name="p491874193011"></a><a name="p491874193011"></a>hardwareReset</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p12918114163011"><a name="p12918114163011"></a><a name="p12918114163011"></a><strong id="b127774583476"><a name="b127774583476"></a><a name="b127774583476"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p4918244309"><a name="p4918244309"></a><a name="p4918244309"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p11919243306"><a name="p11919243306"></a><a name="p11919243306"></a>Resets hardware.</p>
</td>
</tr>
<tr id="row169195410309"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p89191746303"><a name="p89191746303"></a><a name="p89191746303"></a>systemInit</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p8919441302"><a name="p8919441302"></a><a name="p8919441302"></a><strong id="b296543474814"><a name="b296543474814"></a><a name="b296543474814"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p199191941307"><a name="p199191941307"></a><a name="p199191941307"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p391919473014"><a name="p391919473014"></a><a name="p391919473014"></a>Performs system initialization.</p>
</td>
</tr>
<tr id="row159191423012"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p189194417307"><a name="p189194417307"></a><a name="p189194417307"></a>setEnhanceSrobe</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p684922173510"><a name="p684922173510"></a><a name="p684922173510"></a><strong id="b1184122212354"><a name="b1184122212354"></a><a name="b1184122212354"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p1191910419304"><a name="p1191910419304"></a><a name="p1191910419304"></a><strong id="b17674159184914"><a name="b17674159184914"></a><a name="b17674159184914"></a>enable</strong>: specifies whether to enable the enhanced strobe feature.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p69194473011"><a name="p69194473011"></a><a name="p69194473011"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p091904143019"><a name="p091904143019"></a><a name="p091904143019"></a>Sets the enhanced strobe feature.</p>
</td>
</tr>
<tr id="row109197416305"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p791917443010"><a name="p791917443010"></a><a name="p791917443010"></a>switchVoltage</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p180311317351"><a name="p180311317351"></a><a name="p180311317351"></a><strong id="b2803231173514"><a name="b2803231173514"></a><a name="b2803231173514"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p1591912415304"><a name="p1591912415304"></a><a name="p1591912415304"></a><strong id="b5411538185218"><a name="b5411538185218"></a><a name="b5411538185218"></a>volt</strong>: voltage, which can be 3.3 V, 1.8 V, or 1.2 V. It is an enumerated value.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p59196416307"><a name="p59196416307"></a><a name="p59196416307"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p169207416301"><a name="p169207416301"></a><a name="p169207416301"></a>Set the voltage.</p>
</td>
</tr>
<tr id="row1992015417301"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1892014463010"><a name="p1892014463010"></a><a name="p1892014463010"></a>devReadOnly</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1392011411309"><a name="p1392011411309"></a><a name="p1392011411309"></a><strong id="b20848102414403"><a name="b20848102414403"></a><a name="b20848102414403"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p89207418304"><a name="p89207418304"></a><a name="p89207418304"></a>Boolean</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p7920847301"><a name="p7920847301"></a><a name="p7920847301"></a>Checks whether the device is read-only.</p>
</td>
</tr>
<tr id="row1092019483018"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1092034103011"><a name="p1092034103011"></a><a name="p1092034103011"></a>cardPluged</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p2920144123010"><a name="p2920144123010"></a><a name="p2920144123010"></a><strong id="b1685142434016"><a name="b1685142434016"></a><a name="b1685142434016"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p2092014411305"><a name="p2092014411305"></a><a name="p2092014411305"></a>Boolean</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1892094153017"><a name="p1892094153017"></a><a name="p1892094153017"></a>Checks whether the device is removed.</p>
</td>
</tr>
<tr id="row892018413013"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p39201146309"><a name="p39201146309"></a><a name="p39201146309"></a>devBusy</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p9920124193013"><a name="p9920124193013"></a><a name="p9920124193013"></a><strong id="b1885213240408"><a name="b1885213240408"></a><a name="b1885213240408"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1992112419305"><a name="p1992112419305"></a><a name="p1992112419305"></a>Boolean</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p69211417302"><a name="p69211417302"></a><a name="p69211417302"></a>Checks whether the device is engaged.</p>
</td>
</tr>
<tr id="row71064053613"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1511114015361"><a name="p1511114015361"></a><a name="p1511114015361"></a>tune</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p4972240153511"><a name="p4972240153511"></a><a name="p4972240153511"></a><strong id="b1997244017354"><a name="b1997244017354"></a><a name="b1997244017354"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
<p id="p5116409364"><a name="p5116409364"></a><a name="p5116409364"></a><strong id="b2286168195617"><a name="b2286168195617"></a><a name="b2286168195617"></a>cmdCode</strong>: command code of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p711440123610"><a name="p711440123610"></a><a name="p711440123610"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p1411184011368"><a name="p1411184011368"></a><a name="p1411184011368"></a>Tunes</p>
</td>
</tr>
<tr id="row1559214410366"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1559364493618"><a name="p1559364493618"></a><a name="p1559364493618"></a>rescanSdioDev</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p165931944133618"><a name="p165931944133618"></a><a name="p165931944133618"></a><strong id="b0854424164010"><a name="b0854424164010"></a><a name="b0854424164010"></a>cntlr</strong>: structure pointer to the MMC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p15593184493610"><a name="p15593184493610"></a><a name="p15593184493610"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p359384473615"><a name="p359384473615"></a><a name="p359384473615"></a>Scans and adds an SDIO device.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1220893490162704"></a>
The following uses **himci.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 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.
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.
- MMC driver entry reference
```
struct HdfDriverEntry g_mmcDriverEntry = {
.moduleVersion = 1,
.Bind = HimciMmcBind, // See the Bind function.
.Init = HimciMmcInit, // See the Init function.
.Release = HimciMmcRelease, //See the Release function.
.moduleName = "hi3516_mmc_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
HDF_INIT(g_mmcDriverEntry); // Call HDF_INIT to register the driver entry with the HDF framework.
```
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 corresponding device attributes to the **mmc\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mmc:: device {
device0 :: deviceNode {
policy = 2;
priority = 10;
permission = 0644;
moduleName = "hi3516_mmc_driver"; // (Mandatory) Driver name, which must be the same as the 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) Used to configure the private data of the controller. The value must be the same as the controller in mmc_config.hcs.
}
device1 :: deviceNode {
policy = 1;
priority = 20;
permission = 0644;
moduleName = "hi3516_mmc_driver";
serviceName = "HDF_PLATFORM_MMC_1";
deviceMatchAttr = "hi3516_mmc_sd"; // Indicates an SD.
}
device2 :: deviceNode {
policy = 1;
priority = 30;
permission = 0644;
moduleName = "hi3516_mmc_driver";
serviceName = "HDF_PLATFORM_MMC_2";
deviceMatchAttr = "hi3516_mmc_sdio";// Indicates an SDIO.
}
}
}
}
}
```
- **mmc\_config.hcs** configuration reference
```
root {
platform {
mmc_config {
template mmc_controller {// Template configuration. In the template, you can configure the common parameters shared by service nodes.
match_attr = "";
voltDef = 0; // 3.3V
freqMin = 50000; // (Mandatory) Minimum frequency
freqMax = 100000000; // (Mandatory) Maximum frequency
freqDef = 400000; // (Mandatory) Default frequency
maxBlkNum = 2048; // (Mandatory) Maximum block number
maxBlkSize = 512; // (Mandatory) Maximum number of blocks
ocrDef = 0x300000; // (Mandatory) Set the working voltage.
caps2 = 0; // (Mandatory) Set the attribute register. For details, see MmcCaps2 in mmc_caps.h.
regSize = 0x118; // (Mandatory) Register bit width
hostId = 0; // (Mandatory) Host ID
regBasePhy = 0x10020000;// (Mandatory) Physical base address of the register
irqNum = 63; // (Mandatory) Interrupt number
devType = 2; // (Mandatory) Device mode, which can be eMMC, SD, SDIO, or COMBO
caps = 0x0001e045; // (Mandatory) Set the attribute register. For details, see MmcCaps in mmc_caps.h.
}
controller_0x10100000 :: mmc_controller {
match_attr = "hi3516_mmc_emmc";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
hostId = 0;
regBasePhy = 0x10100000;
irqNum = 96;
devType = 0; // The value 0 indicates an embedded MultiMedia card (eMMC).
caps = 0xd001e045;
caps2 = 0x60;
}
controller_0x100f0000 :: mmc_controller {
match_attr = "hi3516_mmc_sd";
hostId = 1;
regBasePhy = 0x100f0000;
irqNum = 62;
devType = 1; // The value 1 indicates a Secure Digital (SD) card.
caps = 0xd001e005;
}
controller_0x10020000 :: mmc_controller {
match_attr = "hi3516_mmc_sdio";
hostId = 2;
regBasePhy = 0x10020000;
irqNum = 63;
devType = 2; // The value 2 indicates a Secure Digital Input Output (SDIO) device.
caps = 0x0001e04d;
}
}
}
}
```
3. Initialize the **MmcCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **MmcCntlrOps** \(used to call underlying functions of the driver\) in **MmcCntlr**, 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 **mmc\_config.hcs** file are read by the HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values are also transferred to the objects at the core layer.
```
struct HimciHost {
struct MmcCntlr *mmc;// (Mandatory) Core layer structure
struct MmcCmd *cmd; // (Mandatory) Core layer structure used to transfer commands. For details about related commands, see MmcCmdCode.
//(Optional) Set parameters based on the vendor's requirements.
void *base;
enum HimciPowerStatus powerStatus;
uint8_t *alignedBuff;
uint32_t buffLen;
struct scatterlist dmaSg;
struct scatterlist *sg;
uint32_t dmaSgNum;
DMA_ADDR_T dmaPaddr;
uint32_t *dmaVaddr;
uint32_t irqNum;
bool isTuning;
uint32_t id;
struct OsalMutex mutex;
bool waitForEvent;
HIMCI_EVENT himciEvent;
};
// MmcCntlr is the core layer controller structure. Its members are assigned with values by using the bind function.
struct MmcCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj;
struct PlatformDevice device;
struct OsalMutex mutex;
struct OsalSem released;
uint32_t devType;
struct MmcDevice *curDev;
struct MmcCntlrOps *ops;
struct PlatformQueue *msgQueue;
uint16_t index;
uint16_t voltDef;
uint32_t vddBit;
uint32_t freqMin;
uint32_t freqMax;
uint32_t freqDef;
union MmcOcr ocrDef;
union MmcCaps caps;
union MmcCaps2 caps2;
uint32_t maxBlkNum;
uint32_t maxBlkSize;
uint32_t maxReqSize;
bool devPluged;
bool detecting;
void *priv;
};
```
- Instantiate the callback function structure **MmcCntlrOps** in **MmcCntlr**. Other members are initialized by using the **Bind** function.
```
static struct MmcCntlrOps g_himciHostOps = {
.request = HimciDoRequest,
.setClock = HimciSetClock,
.setPowerMode = HimciSetPowerMode,
.setBusWidth = HimciSetBusWidth,
.setBusTiming = HimciSetBusTiming,
.setSdioIrq = HimciSetSdioIrq,
.hardwareReset = HimciHardwareReset,
.systemInit = HimciSystemInit,
.setEnhanceSrobe= HimciSetEnhanceSrobe,
.switchVoltage = HimciSwitchVoltage,
.devReadOnly = HimciDevReadOnly,
.devPluged = HimciCardPluged,
.devBusy = HimciDevBusy,
.tune = HimciTune,
.rescanSdioDev = HimciRescanSdioDev,
};
```
- 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.\)
<a name="table1428218958162704"></a>
<table><thead align="left"><tr id="row1723943104162704"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry136979408162704p0"><a name="entry136979408162704p0"></a><a name="entry136979408162704p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry1590766658162704p0"><a name="entry1590766658162704p0"></a><a name="entry1590766658162704p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row408410040162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1337150412162704p0"><a name="entry1337150412162704p0"></a><a name="entry1337150412162704p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2061632106162704p0"><a name="entry2061632106162704p0"></a><a name="entry2061632106162704p0"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row160841211162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1173668571162704p0"><a name="entry1173668571162704p0"></a><a name="entry1173668571162704p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry74350097162704p0"><a name="entry74350097162704p0"></a><a name="entry74350097162704p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row1596857798162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry190784255162704p0"><a name="entry190784255162704p0"></a><a name="entry190784255162704p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1070501269162704p0"><a name="entry1070501269162704p0"></a><a name="entry1070501269162704p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1645995958162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry741922133162704p0"><a name="entry741922133162704p0"></a><a name="entry741922133162704p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2094504256162704p0"><a name="entry2094504256162704p0"></a><a name="entry2094504256162704p0"></a>I/O error</p>
</td>
</tr>
<tr id="row733220922162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1177794681162704p0"><a name="entry1177794681162704p0"></a><a name="entry1177794681162704p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry540896959162704p0"><a name="entry540896959162704p0"></a><a name="entry540896959162704p0"></a>Initialization successful</p>
</td>
</tr>
<tr id="row1890064939162704"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry118676812162704p0"><a name="entry118676812162704p0"></a><a name="entry118676812162704p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry2078272728162704p0"><a name="entry2078272728162704p0"></a><a name="entry2078272728162704p0"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
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)
{
struct MmcCntlr *cntlr = NULL;
struct HimciHost *host = NULL;
int32_t ret;
cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));
host = (struct HimciHost *)OsalMemCalloc(sizeof(struct HimciHost));
host->mmc = cntlr; // (Mandatory) Enable conversion between HimciHost and MmcCntlr.
cntlr->priv = (void *)host; // (Mandatory) Enable conversion between HimciHost and MmcCntlr.
cntlr->ops = &g_himciHostOps; // (Mandatory) Connect to the MmcCntlrOps instance.
cntlr->hdfDevObj = obj; // (Mandatory) Enable conversion between HdfDeviceObject and MmcCntlr.
obj->service = &cntlr->service; // (Mandatory) Enable conversion between HdfDeviceObject and MmcCntlr.
ret = MmcCntlrParse(cntlr, obj); // (Mandatory) Initialize cntlr. If the initialization fails, execute goto _ERR.
...
ret = HimciHostParse(host, obj); // (Mandatory) Initialize the attributes of the host. If the initialization fails, execute goto _ERR.
...
ret = HimciHostInit(host, cntlr);// Initialization defined by the vendor. If the initialization fails, execute goto _ERR.
...
ret = MmcCntlrAdd(cntlr); // Call the function at the core layer. If the function fails to be called, execute goto _ERR.
...
(void)MmcCntlrAddDetectMsgToQueue(cntlr);// Add the card detection message to the queue.
HDF_LOGD("HimciMmcBind: success.");
return HDF_SUCCESS;
_ERR:
HimciDeleteHost(host);
HDF_LOGD("HimciMmcBind: fail, err = %d.", ret);
return ret;
}
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS
Function description:
Implements ProcMciInit.
```
static int32_t HimciMmcInit(struct HdfDeviceObject *obj)
{
static bool procInit = false;
(void)obj;
if (procInit == false) {
if (ProcMciInit() == HDF_SUCCESS) {
procInit = true;
HDF_LOGD("HimciMmcInit: proc init success.");
}
}
HDF_LOGD("HimciMmcInit: 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 framework 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.
```
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.
...
HimciDeleteHost((struct HimciHost *)cntlr->priv);// Memory release function customized by the vendor. A forced conversion from MmcCntlr to HimciHost is involved in the process.
}
```
# PWM<a name="EN-US_TOPIC_0000001160812684"></a>
- [Overview](#section1043395117296)
- [Available APIs](#section3939192652418)
- [Usage Guidelines](#section435718267334)
- [How to Use](#section113655616347)
- [Obtaining a PWM Device Handle](#section17816586359)
- [Setting the PWM Period](#section920214812397)
- [Setting the PWM Duty Cycle](#section519712820405)
- [Setting the PWM Polarity](#section12383334115)
- [Enabling the PWM Device](#section382684811414)
- [Disabling the PWM Device](#section16545114404218)
- [Obtaining PWM Device Configuration Parameters](#section117101243144311)
- [Setting PWM Device Configuration Parameters](#section13834163604414)
- [Releasing the PWM Device Handle](#section12987111511450)
- [Usage Example](#section138636719469)
## Overview<a name="section1043395117296"></a>
- Pulse width modulation \(PWM\) is a method used to digitally encode analog signal levels and convert them into pulses. It can be used for motor control and backlight brightness adjustment.
- The PWM APIs define a set of common functions for operating a PWM device, including those for:
- Obtaining and releasing a PWM device handle
- Setting the PWM period, duty cycle, and polarity
- Enabling and disabling a PWM device
- Obtaining and setting configuration parameters
## Available APIs<a name="section3939192652418"></a>
**Table 1** APIs available for the PWM driver
<a name="table1731550155318"></a>
<table><thead align="left"><tr id="row4419501537"><th class="cellrowborder" align="left" valign="top" width="20.857914208579142%" id="mcps1.2.4.1.1"><p id="p641050105320"><a name="p641050105320"></a><a name="p641050105320"></a>Capability</p>
</th>
<th class="cellrowborder" align="left" valign="top" width="23.36766323367663%" id="mcps1.2.4.1.2"><p id="p54150165315"><a name="p54150165315"></a><a name="p54150165315"></a>Function</p>
</th>
<th class="cellrowborder" align="left" valign="top" width="55.77442255774422%" id="mcps1.2.4.1.3"><p id="p941150145313"><a name="p941150145313"></a><a name="p941150145313"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1651292212306"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p1387414255305"><a name="p1387414255305"></a><a name="p1387414255305"></a>Obtaining/Releasing device handles</p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p8874825143014"><a name="p8874825143014"></a><a name="p8874825143014"></a>PwmOpen</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p1087432513307"><a name="p1087432513307"></a><a name="p1087432513307"></a>Obtains a PWM device handle.</p>
</td>
</tr>
<tr id="row1429083612305"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1956614106311"><a name="p1956614106311"></a><a name="p1956614106311"></a>PwmClose</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p829111362306"><a name="p829111362306"></a><a name="p829111362306"></a>Releases a PWM device handle.</p>
</td>
</tr>
<tr id="row34145016535"><td class="cellrowborder" rowspan="3" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p229610227124"><a name="p229610227124"></a><a name="p229610227124"></a>Setting the PWM period, duty cycle, and polarity</p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p19389143041518"><a name="p19389143041518"></a><a name="p19389143041518"></a>PwmSetPeriod</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p1360544321811"><a name="p1360544321811"></a><a name="p1360544321811"></a>Sets the PWM period.</p>
</td>
</tr>
<tr id="row5632152611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p1392810111722"><a name="p1392810111722"></a><a name="p1392810111722"></a>PwmSetDuty</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p10448193611188"><a name="p10448193611188"></a><a name="p10448193611188"></a>Sets the PWM duty cycle.</p>
</td>
</tr>
<tr id="row1766145611414"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p10445141911213"><a name="p10445141911213"></a><a name="p10445141911213"></a>PwmSetPolarity</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p448643019188"><a name="p448643019188"></a><a name="p448643019188"></a>Sets the PWM polarity.</p>
</td>
</tr>
<tr id="row195531331436"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p166091535331"><a name="p166091535331"></a><a name="p166091535331"></a>Enabling/Disabling devices</p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p85533315315"><a name="p85533315315"></a><a name="p85533315315"></a>PwmEnable</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p855303118314"><a name="p855303118314"></a><a name="p855303118314"></a>Enables a PWM device.</p>
</td>
</tr>
<tr id="row96141928233"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p66151828330"><a name="p66151828330"></a><a name="p66151828330"></a>PwmDisable</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p261518281139"><a name="p261518281139"></a><a name="p261518281139"></a>Disables a PWM device.</p>
</td>
</tr>
<tr id="row1020919129159"><td class="cellrowborder" rowspan="2" valign="top" width="20.857914208579142%" headers="mcps1.2.4.1.1 "><p id="p82092126154"><a name="p82092126154"></a><a name="p82092126154"></a>Obtaining/Setting configuration parameters</p>
<p id="p6794153701111"><a name="p6794153701111"></a><a name="p6794153701111"></a></p>
</td>
<td class="cellrowborder" valign="top" width="23.36766323367663%" headers="mcps1.2.4.1.2 "><p id="p1739013012154"><a name="p1739013012154"></a><a name="p1739013012154"></a>PwmSetConfig</p>
</td>
<td class="cellrowborder" valign="top" width="55.77442255774422%" headers="mcps1.2.4.1.3 "><p id="p1152912417189"><a name="p1152912417189"></a><a name="p1152912417189"></a>Sets PWM device configuration parameters.</p>
</td>
</tr>
<tr id="row379443710118"><td class="cellrowborder" valign="top" headers="mcps1.2.4.1.1 "><p id="p4333154919111"><a name="p4333154919111"></a><a name="p4333154919111"></a>PwmGetConfig</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p id="p19575195601711"><a name="p19575195601711"></a><a name="p19575195601711"></a>Obtains PWM device configuration parameters.</p>
</td>
</tr>
</tbody>
</table>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>All functions described in this document can be called only in kernel space.
## Usage Guidelines<a name="section435718267334"></a>
### How to Use<a name="section113655616347"></a>
[Figure 1](#fig23885455594) shows the process of using a PWM device.
**Figure 1** Process of using a PWM device<a name="fig23885455594"></a>
![](figures/en-us_image_0000001206372673.png)
### Obtaining a PWM Device Handle<a name="section17816586359"></a>
Before performing operations on a PWM device, obtain a PWM device handle by calling **PwmOpen**. This function returns a PWM device handle with the specified device number.
DevHandle PwmOpen\(uint32\_t num\);
**Table 2** Description of PwmOpen
<a name="table7603619123820"></a>
<table><tbody><tr id="row1060351914386"><td class="cellrowborder" valign="top" width="50%"><p id="p14603181917382"><a name="p14603181917382"></a><a name="p14603181917382"></a><strong id="b8660143618196"><a name="b8660143618196"></a><a name="b8660143618196"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p36031519183819"><a name="p36031519183819"></a><a name="p36031519183819"></a><strong id="b3425537181912"><a name="b3425537181912"></a><a name="b3425537181912"></a>Description</strong></p>
</td>
</tr>
<tr id="row1960431983813"><td class="cellrowborder" valign="top" width="50%"><p id="p1114111239269"><a name="p1114111239269"></a><a name="p1114111239269"></a>num</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1560441923818"><a name="p1560441923818"></a><a name="p1560441923818"></a>PWM device number.</p>
</td>
</tr>
<tr id="row380484160"><td class="cellrowborder" valign="top" width="50%"><p id="p460381915385"><a name="p460381915385"></a><a name="p460381915385"></a><strong id="b38961340181918"><a name="b38961340181918"></a><a name="b38961340181918"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p96031619153812"><a name="p96031619153812"></a><a name="p96031619153812"></a><strong id="b1273144114193"><a name="b1273144114193"></a><a name="b1273144114193"></a>Description</strong></p>
</td>
</tr>
<tr id="row5793818161"><td class="cellrowborder" valign="top" width="50%"><p id="p1060418195389"><a name="p1060418195389"></a><a name="p1060418195389"></a>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p760471912388"><a name="p760471912388"></a><a name="p760471912388"></a>Failed to obtain the PWM device handle.</p>
</td>
</tr>
<tr id="row187914871618"><td class="cellrowborder" valign="top" width="50%"><p id="p5604719133811"><a name="p5604719133811"></a><a name="p5604719133811"></a>Device handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p3604181933818"><a name="p3604181933818"></a><a name="p3604181933818"></a>PWM device handle.</p>
</td>
</tr>
</tbody>
</table>
The following example shows how to obtain a PWM device handle with the device number **0**:
```
uint32_t num = 0; /* PWM device number */
DevHandle pwm = NULL; /* PWM device handle */
/* Obtain the PWM device handle. */
pwm = PwmOpen(num);
if (pwm == NULL) {
HDF_LOGE("PwmOpen: pwm%d failed", num);
return;
}
```
### Setting the PWM Period<a name="section920214812397"></a>
int32\_t PwmSetPeriod\(DevHandle handle, uint32\_t period\);
**Table 3** Description of PwmSetPeriod
<a name="table16124612193214"></a>
<table><tbody><tr id="row4124212123217"><td class="cellrowborder" valign="top" width="50%"><p id="p11124131243218"><a name="p11124131243218"></a><a name="p11124131243218"></a><strong id="b1857203711910"><a name="b1857203711910"></a><a name="b1857203711910"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p14124191263210"><a name="p14124191263210"></a><a name="p14124191263210"></a><strong id="b17874123771911"><a name="b17874123771911"></a><a name="b17874123771911"></a>Description</strong></p>
</td>
</tr>
<tr id="row111241012133210"><td class="cellrowborder" valign="top" width="50%"><p id="p18124201220324"><a name="p18124201220324"></a><a name="p18124201220324"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p20124191210321"><a name="p20124191210321"></a><a name="p20124191210321"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row151241112163216"><td class="cellrowborder" valign="top" width="50%"><p id="p712481223212"><a name="p712481223212"></a><a name="p712481223212"></a>period</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1312411126320"><a name="p1312411126320"></a><a name="p1312411126320"></a>Period, in nanoseconds.</p>
</td>
</tr>
<tr id="row712471214320"><td class="cellrowborder" valign="top" width="50%"><p id="p1612421233217"><a name="p1612421233217"></a><a name="p1612421233217"></a><strong id="b13153419197"><a name="b13153419197"></a><a name="b13153419197"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1712591211327"><a name="p1712591211327"></a><a name="p1712591211327"></a><strong id="b79834217190"><a name="b79834217190"></a><a name="b79834217190"></a>Description</strong></p>
</td>
</tr>
<tr id="row812581214326"><td class="cellrowborder" valign="top" width="50%"><p id="p13125812183214"><a name="p13125812183214"></a><a name="p13125812183214"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p15125812193212"><a name="p15125812193212"></a><a name="p15125812193212"></a>Succeeded in setting the PWM period.</p>
</td>
</tr>
<tr id="row2012571273216"><td class="cellrowborder" valign="top" width="50%"><p id="p17125181215327"><a name="p17125181215327"></a><a name="p17125181215327"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p81251512143217"><a name="p81251512143217"></a><a name="p81251512143217"></a>Failed to set the period.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
uint32_t period = 1000; /* Period: 1000 ns */
ret = PwmSetPeriod(pwm, period); /* Set the PWM period. */
if (ret != 0) {
HDF_LOGE("PwmSetPeriod: failed, ret %d", ret);
}
```
### Setting the PWM Duty Cycle<a name="section519712820405"></a>
int32\_t PwmSetDuty\(DevHandle handle, uint32\_t duty\);
**Table 4** Description of PwmSetDuty
<a name="table2010731215368"></a>
<table><tbody><tr id="row51071812163614"><td class="cellrowborder" valign="top" width="50%"><p id="p21071412123617"><a name="p21071412123617"></a><a name="p21071412123617"></a><strong id="b1459173719195"><a name="b1459173719195"></a><a name="b1459173719195"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p910715125363"><a name="p910715125363"></a><a name="p910715125363"></a><strong id="b16877113781915"><a name="b16877113781915"></a><a name="b16877113781915"></a>Description</strong></p>
</td>
</tr>
<tr id="row5107912193611"><td class="cellrowborder" valign="top" width="50%"><p id="p15107141223618"><a name="p15107141223618"></a><a name="p15107141223618"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p16107151293612"><a name="p16107151293612"></a><a name="p16107151293612"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row131077122364"><td class="cellrowborder" valign="top" width="50%"><p id="p4107161218361"><a name="p4107161218361"></a><a name="p4107161218361"></a>duty</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p13107201263620"><a name="p13107201263620"></a><a name="p13107201263620"></a>Duty cycle, in nanoseconds.</p>
</td>
</tr>
<tr id="row161071512143618"><td class="cellrowborder" valign="top" width="50%"><p id="p01071012123617"><a name="p01071012123617"></a><a name="p01071012123617"></a><strong id="b7318164151915"><a name="b7318164151915"></a><a name="b7318164151915"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p10107111273619"><a name="p10107111273619"></a><a name="p10107111273619"></a><strong id="b181001442121915"><a name="b181001442121915"></a><a name="b181001442121915"></a>Description</strong></p>
</td>
</tr>
<tr id="row15108101217363"><td class="cellrowborder" valign="top" width="50%"><p id="p1110811263616"><a name="p1110811263616"></a><a name="p1110811263616"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p61081712203612"><a name="p61081712203612"></a><a name="p61081712203612"></a>Succeeded in setting the duty cycle.</p>
</td>
</tr>
<tr id="row171081012183618"><td class="cellrowborder" valign="top" width="50%"><p id="p610816120365"><a name="p610816120365"></a><a name="p610816120365"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p10108012143617"><a name="p10108012143617"></a><a name="p10108012143617"></a>Failed to set the duty cycle.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
uint32_t duty = 500; /* Duty cycle: 500 ns */
ret = PwmSetDuty(pwm, duty); /* Set the PWM duty cycle. */
if (ret != 0) {
HDF_LOGE("PwmSetDuty: failed, ret %d", ret);
}
```
### Setting the PWM Polarity<a name="section12383334115"></a>
int32\_t PwmSetPolarity\(DevHandle handle, uint8\_t polarity\);
**Table 5** Description of PwmSetPolarity
<a name="table141853773813"></a>
<table><tbody><tr id="row6418837183810"><td class="cellrowborder" valign="top" width="50%"><p id="p14181637103817"><a name="p14181637103817"></a><a name="p14181637103817"></a><strong id="b16133714199"><a name="b16133714199"></a><a name="b16133714199"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p74181375386"><a name="p74181375386"></a><a name="p74181375386"></a><strong id="b1187918371191"><a name="b1187918371191"></a><a name="b1187918371191"></a>Description</strong></p>
</td>
</tr>
<tr id="row84181437163812"><td class="cellrowborder" valign="top" width="50%"><p id="p1141823715384"><a name="p1141823715384"></a><a name="p1141823715384"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p7418143718385"><a name="p7418143718385"></a><a name="p7418143718385"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row5418123711387"><td class="cellrowborder" valign="top" width="50%"><p id="p241893773817"><a name="p241893773817"></a><a name="p241893773817"></a>polarity</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p184181937123811"><a name="p184181937123811"></a><a name="p184181937123811"></a>Polarity, which can be <strong id="b31772419213"><a name="b31772419213"></a><a name="b31772419213"></a>PWM_NORMAL_POLARITY</strong> or <strong id="b31771840212"><a name="b31771840212"></a><a name="b31771840212"></a>PWM_INVERTED_POLARITY</strong>.</p>
</td>
</tr>
<tr id="row841883773819"><td class="cellrowborder" valign="top" width="50%"><p id="p11418193763820"><a name="p11418193763820"></a><a name="p11418193763820"></a><strong id="b17320164117192"><a name="b17320164117192"></a><a name="b17320164117192"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p164185378387"><a name="p164185378387"></a><a name="p164185378387"></a><strong id="b61021427199"><a name="b61021427199"></a><a name="b61021427199"></a>Description</strong></p>
</td>
</tr>
<tr id="row1741919372382"><td class="cellrowborder" valign="top" width="50%"><p id="p2419103718389"><a name="p2419103718389"></a><a name="p2419103718389"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p241993723818"><a name="p241993723818"></a><a name="p241993723818"></a>Succeed in setting the polarity.</p>
</td>
</tr>
<tr id="row1441983711384"><td class="cellrowborder" valign="top" width="50%"><p id="p1441903793817"><a name="p1441903793817"></a><a name="p1441903793817"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p84191237193817"><a name="p84191237193817"></a><a name="p84191237193817"></a>Failed to set the polarity.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
uint8_t polarity = PWM_INVERTED_POLARITY; /* Inverted polarity */
ret = PwmSetPolarity(pwm, polarity); /* Set PWM polarity to inverted polarity. */
if (ret != 0) {
HDF_LOGE("PwmSetPolarity: failed, ret %d", ret);
}
```
### Enabling the PWM Device<a name="section382684811414"></a>
int32\_t PwmEnable\(DevHandle handle\);
**Table 6** Description of PwmEnable
<a name="table785385210447"></a>
<table><tbody><tr id="row9853185234417"><td class="cellrowborder" valign="top" width="50%"><p id="p7853195215444"><a name="p7853195215444"></a><a name="p7853195215444"></a><strong id="b36343761918"><a name="b36343761918"></a><a name="b36343761918"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p4853352104417"><a name="p4853352104417"></a><a name="p4853352104417"></a><strong id="b11881837131919"><a name="b11881837131919"></a><a name="b11881837131919"></a>Description</strong></p>
</td>
</tr>
<tr id="row6853165254419"><td class="cellrowborder" valign="top" width="50%"><p id="p085313525446"><a name="p085313525446"></a><a name="p085313525446"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p185319529444"><a name="p185319529444"></a><a name="p185319529444"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row585313527443"><td class="cellrowborder" valign="top" width="50%"><p id="p15853652174416"><a name="p15853652174416"></a><a name="p15853652174416"></a><strong id="b16323144113194"><a name="b16323144113194"></a><a name="b16323144113194"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1385310525444"><a name="p1385310525444"></a><a name="p1385310525444"></a><strong id="b8104184291915"><a name="b8104184291915"></a><a name="b8104184291915"></a>Description</strong></p>
</td>
</tr>
<tr id="row9854252134410"><td class="cellrowborder" valign="top" width="50%"><p id="p13854155214416"><a name="p13854155214416"></a><a name="p13854155214416"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p6854452114416"><a name="p6854452114416"></a><a name="p6854452114416"></a>Succeeded in enabling the PWM device.</p>
</td>
</tr>
<tr id="row58545526443"><td class="cellrowborder" valign="top" width="50%"><p id="p1085412522449"><a name="p1085412522449"></a><a name="p1085412522449"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p2854052124416"><a name="p2854052124416"></a><a name="p2854052124416"></a>Failed to enable the PWM device.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
ret = PwmEnable(pwm); /* Enable the PWM device. */
if (ret != 0) {
HDF_LOGE("PwmEnable: failed, ret %d", ret);
}
```
### Disabling the PWM Device<a name="section16545114404218"></a>
int32\_t PwmDisable\(DevHandle handle\);
**Table 7** Description of PwmDisable
<a name="table1354973912475"></a>
<table><tbody><tr id="row115499392478"><td class="cellrowborder" valign="top" width="50%"><p id="p1554993912474"><a name="p1554993912474"></a><a name="p1554993912474"></a><strong id="b56503721918"><a name="b56503721918"></a><a name="b56503721918"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p055083915471"><a name="p055083915471"></a><a name="p055083915471"></a><strong id="b088343710192"><a name="b088343710192"></a><a name="b088343710192"></a>Description</strong></p>
</td>
</tr>
<tr id="row1855093974715"><td class="cellrowborder" valign="top" width="50%"><p id="p2550739114717"><a name="p2550739114717"></a><a name="p2550739114717"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1755018397479"><a name="p1755018397479"></a><a name="p1755018397479"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row355043910472"><td class="cellrowborder" valign="top" width="50%"><p id="p1655053984714"><a name="p1655053984714"></a><a name="p1655053984714"></a><strong id="b16327041171912"><a name="b16327041171912"></a><a name="b16327041171912"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p16550439154720"><a name="p16550439154720"></a><a name="p16550439154720"></a><strong id="b101057422194"><a name="b101057422194"></a><a name="b101057422194"></a>Description</strong></p>
</td>
</tr>
<tr id="row25507391479"><td class="cellrowborder" valign="top" width="50%"><p id="p1555014394473"><a name="p1555014394473"></a><a name="p1555014394473"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p15550839174713"><a name="p15550839174713"></a><a name="p15550839174713"></a>Succeeded in disabling the PWM device.</p>
</td>
</tr>
<tr id="row1155093913470"><td class="cellrowborder" valign="top" width="50%"><p id="p1655015398476"><a name="p1655015398476"></a><a name="p1655015398476"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p4550143919471"><a name="p4550143919471"></a><a name="p4550143919471"></a>Failed to disable the PWM device.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
ret = PwmDisable(pwm); /* Disable the PWM device. */
if (ret != 0) {
HDF_LOGE("PwmDisable: failed, ret %d", ret);
}
```
### Obtaining PWM Device Configuration Parameters<a name="section117101243144311"></a>
int32\_t PwmGetConfig\(DevHandle handle, struct PwmConfig \*config\);
**Table 8** Description of PwmGetConfig
<a name="table14209152141313"></a>
<table><tbody><tr id="row1420918529133"><td class="cellrowborder" valign="top" width="50%"><p id="p42091852141314"><a name="p42091852141314"></a><a name="p42091852141314"></a><strong id="b1866173710197"><a name="b1866173710197"></a><a name="b1866173710197"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p202099523137"><a name="p202099523137"></a><a name="p202099523137"></a><strong id="b19885123791911"><a name="b19885123791911"></a><a name="b19885123791911"></a>Description</strong></p>
</td>
</tr>
<tr id="row142091352171310"><td class="cellrowborder" valign="top" width="50%"><p id="p1520915529131"><a name="p1520915529131"></a><a name="p1520915529131"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p720995291310"><a name="p720995291310"></a><a name="p720995291310"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row6209152161314"><td class="cellrowborder" valign="top" width="50%"><p id="p720916522139"><a name="p720916522139"></a><a name="p720916522139"></a>config</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p172091452131319"><a name="p172091452131319"></a><a name="p172091452131319"></a>Pointer to the <strong id="b1844333918213"><a name="b1844333918213"></a><a name="b1844333918213"></a>PwmConfig</strong> structure containing PWM device configuration parameters.</p>
</td>
</tr>
<tr id="row12092522139"><td class="cellrowborder" valign="top" width="50%"><p id="p18209125211134"><a name="p18209125211134"></a><a name="p18209125211134"></a><strong id="b4330164111912"><a name="b4330164111912"></a><a name="b4330164111912"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p420975231318"><a name="p420975231318"></a><a name="p420975231318"></a><strong id="b16107114241910"><a name="b16107114241910"></a><a name="b16107114241910"></a>Description</strong></p>
</td>
</tr>
<tr id="row8209155251310"><td class="cellrowborder" valign="top" width="50%"><p id="p13210145291312"><a name="p13210145291312"></a><a name="p13210145291312"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p152101952141315"><a name="p152101952141315"></a><a name="p152101952141315"></a>Succeeded in obtaining PWM device configuration parameters.</p>
</td>
</tr>
<tr id="row102101452121320"><td class="cellrowborder" valign="top" width="50%"><p id="p10210175219134"><a name="p10210175219134"></a><a name="p10210175219134"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p72101252101312"><a name="p72101252101312"></a><a name="p72101252101312"></a>Failed to obtain PWM device configuration parameters.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
struct PwmConfig config= {0}; /* PWM configuration parameters */
ret = PwmGetConfig(pwm, &config); /* Obtain PWM device configuration parameters. */
if (ret != 0) {
HDF_LOGE("PwmGetConfig: failed, ret %d", ret);
}
```
### Setting PWM Device Configuration Parameters<a name="section13834163604414"></a>
int32\_t PwmSetConfig\(DevHandle handle, struct PwmConfig \*config\);
**Table 9** Description of PwmSetConfig
<a name="table1836117542321"></a>
<table><tbody><tr id="row20361165453211"><td class="cellrowborder" valign="top" width="50%"><p id="p1736135418323"><a name="p1736135418323"></a><a name="p1736135418323"></a><strong id="b11682037161918"><a name="b11682037161918"></a><a name="b11682037161918"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p13361954103214"><a name="p13361954103214"></a><a name="p13361954103214"></a><strong id="b18888173791918"><a name="b18888173791918"></a><a name="b18888173791918"></a>Description</strong></p>
</td>
</tr>
<tr id="row336185416328"><td class="cellrowborder" valign="top" width="50%"><p id="p3361454153218"><a name="p3361454153218"></a><a name="p3361454153218"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p836175418328"><a name="p836175418328"></a><a name="p836175418328"></a>PWM device handle.</p>
</td>
</tr>
<tr id="row18361135411322"><td class="cellrowborder" valign="top" width="50%"><p id="p2036175403217"><a name="p2036175403217"></a><a name="p2036175403217"></a>config</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p1736120541323"><a name="p1736120541323"></a><a name="p1736120541323"></a>Pointer to the <strong id="b886814395214"><a name="b886814395214"></a><a name="b886814395214"></a>PwmConfig</strong> structure containing PWM device configuration parameters.</p>
</td>
</tr>
<tr id="row2361254133217"><td class="cellrowborder" valign="top" width="50%"><p id="p1636295463212"><a name="p1636295463212"></a><a name="p1636295463212"></a><strong id="b0333141131914"><a name="b0333141131914"></a><a name="b0333141131914"></a>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p173621854153217"><a name="p173621854153217"></a><a name="p173621854153217"></a><strong id="b210914211914"><a name="b210914211914"></a><a name="b210914211914"></a>Description</strong></p>
</td>
</tr>
<tr id="row73628543328"><td class="cellrowborder" valign="top" width="50%"><p id="p15362205417325"><a name="p15362205417325"></a><a name="p15362205417325"></a>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p436285433211"><a name="p436285433211"></a><a name="p436285433211"></a>Succeeded in setting PWM configuration parameters.</p>
</td>
</tr>
<tr id="row23621154153220"><td class="cellrowborder" valign="top" width="50%"><p id="p13362954113214"><a name="p13362954113214"></a><a name="p13362954113214"></a>Negative value</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p83629546325"><a name="p83629546325"></a><a name="p83629546325"></a>Failed to set PWM configuration parameters.</p>
</td>
</tr>
</tbody>
</table>
```
int32_t ret;
struct PwmConfig config= {0}; /* PWM configuration parameters */
config.duty = 500; /* Duty cycle: 500 ns */
config.period = 1000; /* Period: 1000 ns */
config.number = 0; /* Continuous output of square waves */
config.polarity = PWM_NORMAL_POLARITY; /* Normal polarity */
ret = PwmSetConfig(pwm, &config); /* Set PWM device configuration parameters. */
if (ret != 0) {
HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret);
}
```
### Releasing the PWM Device Handle<a name="section12987111511450"></a>
void PwmClose\(DevHandle handle\);
This function will release the resources obtained by calling **PwmClose**.
**Table 10** Description of PwmClose
<a name="table72517953115"></a>
<table><tbody><tr id="row1525793312"><td class="cellrowborder" valign="top" width="50%"><p id="p115402031153111"><a name="p115402031153111"></a><a name="p115402031153111"></a><strong id="b1669123714198"><a name="b1669123714198"></a><a name="b1669123714198"></a>Parameter</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p65406313319"><a name="p65406313319"></a><a name="p65406313319"></a><strong id="b8890113710195"><a name="b8890113710195"></a><a name="b8890113710195"></a>Description</strong></p>
</td>
</tr>
<tr id="row1926109193116"><td class="cellrowborder" valign="top" width="50%"><p id="p105419317318"><a name="p105419317318"></a><a name="p105419317318"></a>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p id="p16541153110317"><a name="p16541153110317"></a><a name="p16541153110317"></a>PWM device handle.</p>
</td>
</tr>
</tbody>
</table>
```
PwmClose(pwm); /* Release the PWM device handle */
```
## Usage Example<a name="section138636719469"></a>
The following example shows how to obtain a PWM device handle, set the PWM configuration parameters, enable the PWM device, and finally release the PWM device handle.
```
#include "hdf_log.h"
#include "osal_time.h"
#include "pwm_if.h"
void PwmTestSample(void)
{
int32_t ret;
struct PwmConfig config; /* PWM configuration parameters */
DevHandle pwm = NULL; /* PWM device handle */
pwm = PwmOpen(0); /* Obtain the PWM device handle. */
if (pwm == NULL) {
HDF_LOGE("PwmOpen: pwm0 failed");
return;
}
/* Obtain the PWM device configuration parameters. */
ret = PwmGetConfig(pwm, &config);
if (ret != 0) {
HDF_LOGE("PwmGetConfig: failed, ret %d\n", ret);
goto err;
}
config.duty = 500; /* Duty cycle: 500 ns */
config.period = 1000; /* Period: 1000 ns */
/* Set the PWM device configuration parameters. */
ret = PwmSetConfig(pwm, &config);
if (ret != 0) {
HDF_LOGE("PwmSetConfig: failed, ret %d\n", ret);
goto err;
}
/* Enable the PWM device. */
ret = PwmEnable(pwm);
if (ret != 0) {
HDF_LOGE("PwmEnable: failed, ret %d\n", ret);
goto err;
}
/* Sleep for 10 seconds */
OsalSleep(10);
/* Disable the PWM device. */
ret = PwmDisable(pwm);
if (ret != 0) {
HDF_LOGE("PwmDisable: failed, ret %d\n", ret);
goto err;
}
err:
/* Release the PWM device handle. */
PwmClose(pwm);
}
```
# PWM<a name="EN-US_TOPIC_0000001199714793"></a>
- [Overview](#section1591602238164144)
- [How to Develop](#section967396342164144)
- [PwmMethod](#section14560119104318)
- [Development Example](#section1883877829164144)
## Overview<a name="section1591602238164144"></a>
In the Hardware Driver Foundation \(HDF\) framework, the Pulse Width Modulator \(PWM\) 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 HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
**Figure 1** Independent service mode<a name="fig983655084219"></a>
![](figures/independent-service-mode-10.png "independent-service-mode-10")
## How to Develop<a name="section967396342164144"></a>
The PWM 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **pwm\_config.hcs** file.
3. Instantiate the PWM controller object.
- Initialize **PwmDev**.
- Instantiate **PwmMethod** in the **PwmDev** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [PwmMethod](#section14560119104318) and [Table 1](#table11173154124311).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the PWM control status and response to interrupts.
### PwmMethod<a name="section14560119104318"></a>
```
struct PwmMethod {
int32_t (*setConfig)(struct PwmDev *pwm, struct PwmConfig *config);
int32_t (*open)(struct PwmDev *pwm);
int32_t (*close)(struct PwmDev *pwm);
};
```
**Table 1** Callbacks for the members in the PwmMethod structure
<a name="table11173154124311"></a>
<table><thead align="left"><tr id="row2173441164311"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p17174144144310"><a name="p17174144144310"></a><a name="p17174144144310"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p21751441154318"><a name="p21751441154318"></a><a name="p21751441154318"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p191751741144313"><a name="p191751741144313"></a><a name="p191751741144313"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p5175641154315"><a name="p5175641154315"></a><a name="p5175641154315"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row7175154144311"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p3900552134317"><a name="p3900552134317"></a><a name="p3900552134317"></a>setConfig</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p422655084417"><a name="p422655084417"></a><a name="p422655084417"></a><strong id="b25915520521"><a name="b25915520521"></a><a name="b25915520521"></a>pwm</strong>: structure pointer to the PWM controller at the core layer.</p>
<p id="p02275502443"><a name="p02275502443"></a><a name="p02275502443"></a><strong id="b138214155312"><a name="b138214155312"></a><a name="b138214155312"></a>config</strong>: structure pointer to the input attribute value.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p18176184112433"><a name="p18176184112433"></a><a name="p18176184112433"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p5176124164314"><a name="p5176124164314"></a><a name="p5176124164314"></a>Configures attributes.</p>
</td>
</tr>
<tr id="row217654124312"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p121761041144314"><a name="p121761041144314"></a><a name="p121761041144314"></a>open</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p2176941144314"><a name="p2176941144314"></a><a name="p2176941144314"></a><strong id="b53894825318"><a name="b53894825318"></a><a name="b53894825318"></a>pwm</strong>: structure pointer to the PWM controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1317694119435"><a name="p1317694119435"></a><a name="p1317694119435"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p376133118453"><a name="p376133118453"></a><a name="p376133118453"></a>Starts the device.</p>
</td>
</tr>
<tr id="row8176174110439"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p017684174314"><a name="p017684174314"></a><a name="p017684174314"></a>close</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1217694118437"><a name="p1217694118437"></a><a name="p1217694118437"></a><strong id="b839310895317"><a name="b839310895317"></a><a name="b839310895317"></a>pwm</strong>: structure pointer to the PWM controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p16176104115437"><a name="p16176104115437"></a><a name="p16176104115437"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p10893332114514"><a name="p10893332114514"></a><a name="p10893332114514"></a>Stops the device.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1883877829164144"></a>
The following uses **pwm\_hi35xx.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 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.
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.
- PWM driver entry reference
```
struct HdfDriverEntry g_hdfPwm = {
.moduleVersion = 1,
.moduleName = "HDF_PLATFORM_PWM",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.Bind = HdfPwmBind,
.Init = HdfPwmInit,
.Release = HdfPwmRelease,
};
// Call HDF_INIT to register the driver entry with the HDF framework.
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 corresponding device attributes to the **pwm\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_pwm :: device {// Configure an HDF device node for each PWM controller. Set this parameter only when there are multiple PWM controllers.
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 the 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.
// For details about the controller information, see pwm_config.hcs.
}
device1 :: deviceNode {
policy = 1;
priority = 80;
permission = 0644;
moduleName = "HDF_PLATFORM_PWM";
serviceName = "HDF_PLATFORM_PWM_1";
deviceMatchAttr = "hisilicon_hi35xx_pwm_1";
}
}
}
}
}
```
- **pwm\_config.hcs** configuration reference
```
root {
platform {
pwm_config {
template pwm_device {// (Mandatory) Template configuration. In the template, you can configure the common parameters shared by service nodes.
serviceName = "";
match_attr = "";
num = 0; // (Mandatory) Device number
base = 0x12070000; // (Mandatory) Used for address mapping
}
device_0x12070000 :: pwm_device {
match_attr = "hisilicon_hi35xx_pwm_0";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
}
device_0x12070020::pwm_device {// Set this parameter only when there are multiple devices.
match_attr = "hisilicon_hi35xx_pwm_1";
num = 1;
base = 0x12070020; // (Mandatory) Used for address mapping
}
}
}
}
```
3. Initialize the **PwmDev** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **PwmMethod** \(used to call underlying functions of the driver\) in **PwmDev**, 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 **pwm\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer.
```
struct HiPwm {
struct PwmDev dev; // (Mandatory) Core layer structure
volatile unsigned char *base;
struct HiPwmRegs *reg; // Device attribute structure, which can be customized.
bool supportPolarity;
};
// PwmDev is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct PwmDev {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct PwmConfig cfg; // Attribute structure. For details, see the description of PwmConfig.
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.
};
struct PwmConfig {
uint32_t duty; // Time (in ns) when a signal is in the on state.
uint32_t period; // Regular interval (in ns) of PWM
uint32_t number; // Number of consecutive PWMs
uint8_t polarity; // Polarity
// ------------------- | --------------
// PWM_NORMAL_POLARITY | Normal polarity
// PWM_INVERTED_POLARITY | Inverted polarity
//
uint8_t status; // Running status
// ------------------ | -----------------
// PWM_DISABLE_STATUS | Disabled
// PWM_ENABLE_STATUS | Enabled
};
```
- Instantiate the callback function structure **PwmMethod** in **PwmDev**. Other members are initialized by using the **Init** function.
```
// Example in pwm_hi35xx.c: fill the hook function
struct PwmMethod g_pwmOps = {
.setConfig = HiPwmSetConfig,// Configure attributes.
};
```
- Init 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.\)
<a name="table1057438215164144"></a>
<table><thead align="left"><tr id="row31521027164144"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry1990732428164144p0"><a name="entry1990732428164144p0"></a><a name="entry1990732428164144p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry2123581292164144p0"><a name="entry2123581292164144p0"></a><a name="entry2123581292164144p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1749271383164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry202330388164144p0"><a name="entry202330388164144p0"></a><a name="entry202330388164144p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1717598064164144p0"><a name="entry1717598064164144p0"></a><a name="entry1717598064164144p0"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row1715354988164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry450625221164144p0"><a name="entry450625221164144p0"></a><a name="entry450625221164144p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry361497788164144p0"><a name="entry361497788164144p0"></a><a name="entry361497788164144p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row1202091366164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry370837906164144p0"><a name="entry370837906164144p0"></a><a name="entry370837906164144p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry353311523164144p0"><a name="entry353311523164144p0"></a><a name="entry353311523164144p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row602018308164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1984036607164144p0"><a name="entry1984036607164144p0"></a><a name="entry1984036607164144p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1221756048164144p0"><a name="entry1221756048164144p0"></a><a name="entry1221756048164144p0"></a>I/O error</p>
</td>
</tr>
<tr id="row47997479164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1220816374164144p0"><a name="entry1220816374164144p0"></a><a name="entry1220816374164144p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1903499126164144p0"><a name="entry1903499126164144p0"></a><a name="entry1903499126164144p0"></a>Initialization successful</p>
</td>
</tr>
<tr id="row2031856197164144"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry463793674164144p0"><a name="entry463793674164144p0"></a><a name="entry463793674164144p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry516362874164144p0"><a name="entry516362874164144p0"></a><a name="entry516362874164144p0"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
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.
static int32_t HdfPwmBind(struct HdfDeviceObject *obj)
{
(void)obj;
return HDF_SUCCESS;
}
static int32_t HdfPwmInit(struct HdfDeviceObject *obj)
{
int ret;
struct HiPwm *hp = NULL;
...
hp = (struct HiPwm *)OsalMemCalloc(sizeof(*hp));
...
ret = HiPwmProbe(hp, obj); // (Mandatory) The implementation is as follows:
...
return ret;
}
static int32_t HiPwmProbe(struct HiPwm *hp, struct HdfDeviceObject *obj)
{
uint32_t tmp;
struct DeviceResourceIface *iface = NULL;
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; // Connect to the instantiated object of PwmMethod.
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 the hp->dev devices and services.
OsalIoUnmap((void *)hp->base);
return HDF_FAILURE;
}
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 framework 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)
{
struct HiPwm *hp = NULL;
...
hp = (struct HiPwm *)obj->service;// A forced conversion from HdfDeviceObject to HiPwm is involved.
...
PwmDeviceRemove(obj, &(hp->dev));// (Mandatory) Call the core layer functions to release PwmDev devices and services. A forced conversion from HiPwm to PwmDev is involved in the process.
HiPwmRemove(hp); //Release HiPwm.
}
```
# RTC<a name="EN-US_TOPIC_0000001051778226"></a>
# RTC<a name="EN-US_TOPIC_0000001206373007"></a>
- [Overview](#section104842041574)
- [Available APIs](#section3373340142215)
- [Available APIs](#section20331159102519)
- [Usage Guidelines](#section20636145604113)
- [How to Use](#section16919828134215)
- [Creating an RTC Device Handle](#section1131212144310)
......@@ -16,7 +15,7 @@
The real-time clock \(RTC\) driver provides precise real time for the operating system \(OS\). If the OS is powered off, the RTC driver continues to keep track of the system time using an external battery.
### Available APIs<a name="section3373340142215"></a>
## Available APIs<a name="section20331159102519"></a>
**Table 1** APIs provided by the RTC driver
......@@ -116,12 +115,10 @@ The real-time clock \(RTC\) driver provides precise real time for the operating
During the OS startup, the HDF loads the RTC driver based on the configuration file. The RTC driver detects the RTC component and initializes the driver.
[Figure 1](#fig166181128151112) illustrates the process of using an RTC device.
**Figure 1** Process of using an RTC device<a name="fig166181128151112"></a>
[Figure 1](#fig1610020107333) illustrates the process of using an RTC device.
![](figure/en-us_image_0000001123675706.png)
**Figure 1** Process of using an RTC device<a name="fig1610020107333"></a>
![](figures/process-of-using-an-rtc-device.png "process-of-using-an-rtc-device")
### Creating an RTC Device Handle<a name="section1131212144310"></a>
......
# RTC<a name="EN-US_TOPIC_0000001153785954"></a>
- [Overview](#section509989381142407)
- [How to Develop](#section1784450860142407)
- [RtcMethod](#section13652132473017)
- [Development Example](#section1594883301142407)
## Overview<a name="section509989381142407"></a>
In the Hardware Driver Foundation \(HDF\) framework, the real-time clock \(RTC\) 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.
**Figure 1** Independent service mode<a name="fig6742142611299"></a>
![](figures/independent-service-mode-11.png "independent-service-mode-11")
## How to Develop<a name="section1784450860142407"></a>
The RTC 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **rtc\_config.hcs** file.
3. Instantiate the RTC controller object.
- Initialize **RtcHost**.
- Instantiate **RtcMethod** in the **RtcHost** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [RtcMethod](#section13652132473017) and [Table 1](#table12929217311).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the RTC control status and response to interrupts.
### RtcMethod<a name="section13652132473017"></a>
```
struct RtcMethod {
int32_t (*ReadTime)(struct RtcHost *host, struct RtcTime *time);
int32_t (*WriteTime)(struct RtcHost *host, const struct RtcTime *time);
int32_t (*ReadAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, struct RtcTime *time);
int32_t (*WriteAlarm)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, const struct RtcTime *time);
int32_t (*RegisterAlarmCallback)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb);
int32_t (*AlarmInterruptEnable)(struct RtcHost *host, enum RtcAlarmIndex alarmIndex, uint8_t enable);
int32_t (*GetFreq)(struct RtcHost *host, uint32_t *freq);
int32_t (*SetFreq)(struct RtcHost *host, uint32_t freq);
int32_t (*Reset)(struct RtcHost *host);
int32_t (*ReadReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t *value);
int32_t (*WriteReg)(struct RtcHost *host, uint8_t usrDefIndex, uint8_t value);
};
```
**Table 1** Callbacks for the members in the RtcMethod structure
<a name="table12929217311"></a>
<table><thead align="left"><tr id="row293621203111"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p15932212314"><a name="p15932212314"></a><a name="p15932212314"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p1193421113111"><a name="p1193421113111"></a><a name="p1193421113111"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p179312214317"><a name="p179312214317"></a><a name="p179312214317"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p993521163113"><a name="p993521163113"></a><a name="p993521163113"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p5931821123115"><a name="p5931821123115"></a><a name="p5931821123115"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1093521113114"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p14941421163112"><a name="p14941421163112"></a><a name="p14941421163112"></a>ReadTime</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p094112118314"><a name="p094112118314"></a><a name="p094112118314"></a><strong id="b1264214345404"><a name="b1264214345404"></a><a name="b1264214345404"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p19945219318"><a name="p19945219318"></a><a name="p19945219318"></a><strong id="b6902125819406"><a name="b6902125819406"></a><a name="b6902125819406"></a>time</strong>: structure pointer to the output time value.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p20941021143120"><a name="p20941021143120"></a><a name="p20941021143120"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p094132115317"><a name="p094132115317"></a><a name="p094132115317"></a>Reads the RTC time information.</p>
</td>
</tr>
<tr id="row199472183111"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p69418214318"><a name="p69418214318"></a><a name="p69418214318"></a>WriteTime</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p10306227052"><a name="p10306227052"></a><a name="p10306227052"></a><strong id="b1330617271556"><a name="b1330617271556"></a><a name="b1330617271556"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p89418214311"><a name="p89418214311"></a><a name="p89418214311"></a><strong id="b1411813377426"><a name="b1411813377426"></a><a name="b1411813377426"></a>time</strong>: structure pointer to the input time.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p3944214314"><a name="p3944214314"></a><a name="p3944214314"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1194321113112"><a name="p1194321113112"></a><a name="p1194321113112"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p5941521123118"><a name="p5941521123118"></a><a name="p5941521123118"></a>Writes the RTC time information (from milliseconds to years).</p>
</td>
</tr>
<tr id="row4941521113111"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p19462119319"><a name="p19462119319"></a><a name="p19462119319"></a>ReadAlarm</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1362015341251"><a name="p1362015341251"></a><a name="p1362015341251"></a><strong id="b14620934553"><a name="b14620934553"></a><a name="b14620934553"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p9951721113113"><a name="p9951721113113"></a><a name="p9951721113113"></a><strong id="b477221417458"><a name="b477221417458"></a><a name="b477221417458"></a>alarmIndex</strong>: clock alarm index, which is an enumerated value.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1995921113112"><a name="p1995921113112"></a><a name="p1995921113112"></a><strong id="b0371144014414"><a name="b0371144014414"></a><a name="b0371144014414"></a>time</strong>: structure pointer to the output time.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p10951721133115"><a name="p10951721133115"></a><a name="p10951721133115"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p14951121193113"><a name="p14951121193113"></a><a name="p14951121193113"></a>Reads the RTC alarm time.</p>
</td>
</tr>
<tr id="row6957211313"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p129517219311"><a name="p129517219311"></a><a name="p129517219311"></a>WriteAlarm</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p136914402055"><a name="p136914402055"></a><a name="p136914402055"></a><strong id="b176918401258"><a name="b176918401258"></a><a name="b176918401258"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p11512468517"><a name="p11512468517"></a><a name="p11512468517"></a><strong id="b195114613519"><a name="b195114613519"></a><a name="b195114613519"></a>alarmIndex</strong>: clock alarm index, which is an enumerated value.</p>
<p id="p595152114315"><a name="p595152114315"></a><a name="p595152114315"></a><strong id="b1892302045019"><a name="b1892302045019"></a><a name="b1892302045019"></a>time</strong>: structure pointer to the input time.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p16951321203115"><a name="p16951321203115"></a><a name="p16951321203115"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p195321113116"><a name="p195321113116"></a><a name="p195321113116"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1095122163116"><a name="p1095122163116"></a><a name="p1095122163116"></a>Writes the RTC alarm time.</p>
</td>
</tr>
<tr id="row1495021173112"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p795421193118"><a name="p795421193118"></a><a name="p795421193118"></a>RegisterAlarmCallback</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p7793145219520"><a name="p7793145219520"></a><a name="p7793145219520"></a><strong id="b37931529513"><a name="b37931529513"></a><a name="b37931529513"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p109352055359"><a name="p109352055359"></a><a name="p109352055359"></a><strong id="b393518551159"><a name="b393518551159"></a><a name="b393518551159"></a>alarmIndex</strong>: clock alarm index, which is an enumerated value.</p>
<p id="p1295182163112"><a name="p1295182163112"></a><a name="p1295182163112"></a><strong id="b11371112513"><a name="b11371112513"></a><a name="b11371112513"></a>cb</strong>: pointer to the callback.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p79582123118"><a name="p79582123118"></a><a name="p79582123118"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1996122173116"><a name="p1996122173116"></a><a name="p1996122173116"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p39602133113"><a name="p39602133113"></a><a name="p39602133113"></a>Registers <strong id="b176627580513"><a name="b176627580513"></a><a name="b176627580513"></a>RtcAlarmCallback</strong> that will be invoked when an alarm is generated at the specified time.</p>
</td>
</tr>
<tr id="row6961321113110"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p129682193119"><a name="p129682193119"></a><a name="p129682193119"></a>AlarmInterruptEnable</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p796015120619"><a name="p796015120619"></a><a name="p796015120619"></a><strong id="b149601210611"><a name="b149601210611"></a><a name="b149601210611"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p174501061561"><a name="p174501061561"></a><a name="p174501061561"></a><strong id="b7450562062"><a name="b7450562062"></a><a name="b7450562062"></a>alarmIndex</strong>: clock alarm index, which is an enumerated value.</p>
<p id="p59682173112"><a name="p59682173112"></a><a name="p59682173112"></a><strong id="b6999711105518"><a name="b6999711105518"></a><a name="b6999711105518"></a>enable</strong>: specifies whether to enable the RTC alarm interrupt.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p5962021123110"><a name="p5962021123110"></a><a name="p5962021123110"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p16961621143119"><a name="p16961621143119"></a><a name="p16961621143119"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p996182112316"><a name="p996182112316"></a><a name="p996182112316"></a>Enables or disables the RTC alarm interrupt.</p>
</td>
</tr>
<tr id="row199622114317"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p09615216315"><a name="p09615216315"></a><a name="p09615216315"></a>GetFreq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p16961021103119"><a name="p16961021103119"></a><a name="p16961021103119"></a><strong id="b17147182285715"><a name="b17147182285715"></a><a name="b17147182285715"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p09620218318"><a name="p09620218318"></a><a name="p09620218318"></a><strong id="b11413184435713"><a name="b11413184435713"></a><a name="b11413184435713"></a>freq</strong>: pointer to the output frequency, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p15961121163111"><a name="p15961121163111"></a><a name="p15961121163111"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p3968214311"><a name="p3968214311"></a><a name="p3968214311"></a>Reads the frequency of the external crystal oscillator connected to the RTC driver.</p>
</td>
</tr>
<tr id="row29692120319"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1296421103115"><a name="p1296421103115"></a><a name="p1296421103115"></a>SetFreq</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p38121311169"><a name="p38121311169"></a><a name="p38121311169"></a><strong id="b481218117612"><a name="b481218117612"></a><a name="b481218117612"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p79792114315"><a name="p79792114315"></a><a name="p79792114315"></a><strong id="b1220510308"><a name="b1220510308"></a><a name="b1220510308"></a>freq</strong>: input frequency, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p4971021103118"><a name="p4971021103118"></a><a name="p4971021103118"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p109772117315"><a name="p109772117315"></a><a name="p109772117315"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p11971621193115"><a name="p11971621193115"></a><a name="p11971621193115"></a>Sets the frequency of the external crystal oscillator connected to the RTC driver.</p>
</td>
</tr>
<tr id="row1697112123114"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p99712117318"><a name="p99712117318"></a><a name="p99712117318"></a>Reset</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p169712123111"><a name="p169712123111"></a><a name="p169712123111"></a><strong id="b13129173210577"><a name="b13129173210577"></a><a name="b13129173210577"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p3974213312"><a name="p3974213312"></a><a name="p3974213312"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p109718210315"><a name="p109718210315"></a><a name="p109718210315"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p197112116316"><a name="p197112116316"></a><a name="p197112116316"></a>Resets the RTC.</p>
</td>
</tr>
<tr id="row3971821103115"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p2971221173111"><a name="p2971221173111"></a><a name="p2971221173111"></a>ReadReg</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p12704168619"><a name="p12704168619"></a><a name="p12704168619"></a><strong id="b1570171616616"><a name="b1570171616616"></a><a name="b1570171616616"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p18975210312"><a name="p18975210312"></a><a name="p18975210312"></a><strong id="b1020311128520"><a name="b1020311128520"></a><a name="b1020311128520"></a>usrDefIndex</strong>: structure defining the index of a custom register.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p14975211314"><a name="p14975211314"></a><a name="p14975211314"></a><strong id="b10580501973"><a name="b10580501973"></a><a name="b10580501973"></a>value</strong>: pointer to the output register 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="p15981221193114"><a name="p15981221193114"></a><a name="p15981221193114"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1098821143115"><a name="p1098821143115"></a><a name="p1098821143115"></a>Reads the configuration of a custom RTC register based on the register index. One index corresponds to one byte of the configuration value.</p>
</td>
</tr>
<tr id="row1298102119313"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p598121153114"><a name="p598121153114"></a><a name="p598121153114"></a>WriteReg</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1747714196613"><a name="p1747714196613"></a><a name="p1747714196613"></a><strong id="b6477519469"><a name="b6477519469"></a><a name="b6477519469"></a>host</strong>: structure pointer to the RTC controller at the core layer.</p>
<p id="p1527912317612"><a name="p1527912317612"></a><a name="p1527912317612"></a><strong id="b72791123968"><a name="b72791123968"></a><a name="b72791123968"></a>usrDefIndex</strong>: structure defining the index of a custom register.</p>
<p id="p1498172173115"><a name="p1498172173115"></a><a name="p1498172173115"></a><strong id="b68893701014"><a name="b68893701014"></a><a name="b68893701014"></a>value</strong>: input register value, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p1998162193110"><a name="p1998162193110"></a><a name="p1998162193110"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p198162173118"><a name="p198162173118"></a><a name="p198162173118"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p13981421203110"><a name="p13981421203110"></a><a name="p13981421203110"></a>Configure the RTC register based on the register index. One index corresponds to one byte of the configuration value.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1594883301142407"></a>
The following uses **rtc\_hi35xx.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 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.
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.
- RTC driver entry reference
```
struct HdfDriverEntry g_rtcDriverEntry = {
.moduleVersion = 1,
.Bind = HiRtcBind, // See the Bind function.
.Init = HiRtcInit, // See the Init function.
.Release = HiRtcRelease, //See the Release function.
.moduleName = "HDF_PLATFORM_RTC", // (Mandatory) This parameter must be the same as that in the .hcs file.
};
// Call HDF_INIT to register the driver entry with the HDF framework.
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. 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.
- **device\_info.hcs** configuration reference
```
root {
device_info {
platform :: host {
device_rtc :: device {
device0 :: deviceNode {
policy = 1; // 2: The driver publishes user-mode services. 1: The driver publishes kernel-mode services. 0: No service needs to be published.
priority = 30; // A smaller value indicates a higher priority.
permission = 0644; // Permission for the driver to create a device node
moduleName = "HDF_PLATFORM_RTC"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
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.
}
}
}
}
}
```
- **rtc\_config.hcs** configuration reference
```
root {
platform {
rtc_config {
controller_0x12080000 {
match_attr = "hisilicon_hi35xx_rtc";// (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
rtcSpiBaseAddr = 0x12080000; // Used for address mapping
regAddrLength = 0x100; // Used for address mapping
irq = 37; // Interruption number
supportAnaCtrl = false;
supportLock = false;
anaCtrlAddr = 0xff;
lock0Addr = 0xff;
lock1Addr = 0xff;
lock2Addr = 0xff;
lock3Addr = 0xff;
}
}
}
}
```
3. Initialize the **RtcHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **RtcMethod** \(used to call underlying functions of the driver\) in **RtcHost**, 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 **rtc\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**.
```
struct RtcConfigInfo {
uint32_t spiBaseAddr; // Used for address mapping
volatile void *remapBaseAddr; // Used for address mapping
uint16_t regAddrLength; // Used for address mapping
uint8_t supportAnaCtrl; // Indicates whether anaCtrl is supported.
uint8_t supportLock; // Indicates whether lock is supported.
uint8_t irq; // Interrupt number
uint8_t alarmIndex; // Clock 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. Its members are assigned with values by using the Init function.
struct RtcHost {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct RtcMethod *method;
void *data;
};
```
- Instantiate the callback function structure **RtcMethod** in **RtcHost**. Other members are initialized by using the **Init** function.
```
// 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 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="table14285177465"></a>
<table><thead align="left"><tr id="row6280177461"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p528181764613"><a name="p528181764613"></a><a name="p528181764613"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p192891754615"><a name="p192891754615"></a><a name="p192891754615"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1328191713465"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p02812173467"><a name="p02812173467"></a><a name="p02812173467"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p142861714610"><a name="p142861714610"></a><a name="p142861714610"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row19288170464"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p16282017184619"><a name="p16282017184619"></a><a name="p16282017184619"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p02841754611"><a name="p02841754611"></a><a name="p02841754611"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row229131734619"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p429171784617"><a name="p429171784617"></a><a name="p429171784617"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1229151764617"><a name="p1229151764617"></a><a name="p1229151764617"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row6291017154612"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p15294179461"><a name="p15294179461"></a><a name="p15294179461"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p329517154617"><a name="p329517154617"></a><a name="p329517154617"></a>I/O error</p>
</td>
</tr>
<tr id="row9298171469"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p13297172461"><a name="p13297172461"></a><a name="p13297172461"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11299171460"><a name="p11299171460"></a><a name="p11299171460"></a>Initialization successful</p>
</td>
</tr>
<tr id="row122911175467"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p32931744612"><a name="p32931744612"></a><a name="p32931744612"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p102911724610"><a name="p102911724610"></a><a name="p102911724610"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Associates the **HdfDeviceObject** object and **RtcHost**.
```
static int32_t HiRtcBind(struct HdfDeviceObject *device)
{
struct RtcHost *host = NULL;
host = RtcHostCreate(device); // Apply for memory and connect to the device: host->device = device;
// Enable conversion between HdfDeviceObject and RtcHost.
...
device->service = &host->service; // Enable conversion between HdfDeviceObject and RtcHost.
// This setting enables the host to be globally used by calling RtcHostFromDevice.
return HDF_SUCCESS;
}
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
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);// A forced conversion from HdfDeviceObject to RtcHost is involved.
rtcInfo = OsalMemCalloc(sizeof(*rtcInfo));
...
// HiRtcConfigData reads attributes from the device configuration tree and fills in supportAnaCtrl, supportLock, spiBaseAddr, regAddrLength, and irq in rtcInfo.
// Provide parameters for HiRtcSwInit and HiRtcSwInit, and perform operations such as releasing memory when the function internal processing fails.
if (HiRtcConfigData(rtcInfo, device->property) != 0) {
...
}
if (HiRtcSwInit(rtcInfo)! = 0) {// Related to address mapping and interrupt registration
...
}
if (HiRtcHwInit(rtcInfo)! = 0) {// Initialize anaCtrl and lockAddr.
...
}
host->method = &g_method; // Connect to the UARTHostMethod instance.
host->data = rtcInfo; // Enable conversion between RtcConfigInfo and RtcHost.
HDF_LOGI("Hdf dev service:%s init success!", HdfDeviceGetServiceName(device));
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 framework 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)
{
struct RtcHost *host = NULL;
struct RtcConfigInfo *rtcInfo = NULL;
...
host = RtcHostFromDevice(device); // A forced conversion from HdfDeviceObject to RtcHost is involved.
rtcInfo = (struct RtcConfigInfo *)host->data;// A forced conversion from RtcHost to RtcConfigInfo is involved.
if (rtcInfo != NULL) {
HiRtcSwExit(rtcInfo);
OsalMemFree(rtcInfo); // Release RtcConfigInfo.
host->data = NULL;
}
RtcHostDestroy(host); // Release RtcHost.
}
```
# SDIO<a name="EN-US_TOPIC_0000001053055057"></a>
# SDIO<a name="EN-US_TOPIC_0000001160653028"></a>
- [Overview](#section1155271783811)
- [Available APIs](#section08064247248)
- [Available APIs](#section12601496259)
- [Usage Guidelines](#section1878939192515)
- [How to Use](#section1490685512255)
- [Opening an SDIO Controller](#section10782428132616)
......@@ -32,11 +31,11 @@
**Figure 1** Connections between the host and devices in SDIO<a name="fig1185316527498"></a>
![](figure/en-us_image_0000001054280608.png)
![](figures/en-us_image_0000001160971556.png)
- The SDIO interface defines a set of common methods for operating an SDIO device, including opening and closing an SDIO controller, exclusively claiming and releasing the host, enabling and disabling devices, claiming and releasing an SDIO IRQ, reading and writing data based on SDIO, and obtaining and setting common information.
### Available APIs<a name="section08064247248"></a>
## Available APIs<a name="section12601496259"></a>
**Table 1** APIs available for the SDIO driver
......@@ -170,7 +169,7 @@
**Figure 2** Process of using an SDIO<a name="fig1343742311264"></a>
![](figure/en-us_image_0000001123540984.png)
![](figures/en-us_image_0000001206291517.png)
### Opening an SDIO Controller<a name="section10782428132616"></a>
......
# SDIO<a name="EN-US_TOPIC_0000001199682295"></a>
- [Overview](#section1347805272150053)
- [How to Develop](#section581179475150053)
- [SdioDeviceOps](#section482911395315)
- [Development Example](#section2112250242150053)
## Overview<a name="section1347805272150053"></a>
A Secure Digital Input Output \(SDIO\) card is an extension of the SD specification to cover I/O functions. SD and SDIO are called multimedia card \(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.
**Figure 1** Independent service mode<a name="fig124181331222"></a>
![](figures/independent-service-mode-12.png "independent-service-mode-12")
## How to Develop<a name="section581179475150053"></a>
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 framework.
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:**
>For details, see [SdioDeviceOps](#section482911395315) and [Table 1](#table878215448417).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the SDIO control status and response to interrupts.
### SdioDeviceOps<a name="section482911395315"></a>
```
// Function template
struct SdioDeviceOps {
int32_t (*incrAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
int32_t (*incrAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
int32_t (*fixedAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
int32_t (*fixedAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);
int32_t (*func0ReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
int32_t (*func0WriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);
int32_t (*setBlockSize)(struct SdioDevice *dev, uint32_t blockSize);
int32_t (*getCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);
int32_t (*setCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);
int32_t (*flushData)(struct SdioDevice *dev);
int32_t (*enableFunc)(struct SdioDevice *dev);
int32_t (*disableFunc)(struct SdioDevice *dev);
int32_t (*claimIrq)(struct SdioDevice *dev, SdioIrqHandler *irqHandler);
int32_t (*releaseIrq)(struct SdioDevice *dev);
int32_t (*findFunc)(struct SdioDevice *dev, struct SdioFunctionConfig *configData);
int32_t (*claimHost)(struct SdioDevice *dev);
int32_t (*releaseHost)(struct SdioDevice *dev);
};
```
**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:**
>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**
## 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 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.
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 framework.
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) It is set to 2. For details, see mmc_config.hcs.
devType = 2; // (Mandatory) It is set 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 framework 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.
}
```
# SPI<a name="EN-US_TOPIC_0000001053057951"></a>
# SPI<a name="EN-US_TOPIC_0000001206171293"></a>
- [Overview](#section193356154511)
- [Available APIs](#section232141411476)
- [Available APIs](#section1325964832615)
- [Usage Guidelines](#section71363452477)
- [How to Use](#section32846814820)
- [Obtaining an SPI Device Handle](#section1927265711481)
......@@ -24,12 +23,10 @@
- CS: signals enabled by an SPI device and controlled by the SPI controller
- [Figure 1](#fig15227181812587) shows the connection between one SPI controller and two SPI devices \(device A and device B\). In this figure, device A and device B share three pins \(SCLK, MISO, and MOSI\) of the controller. CS0 of device A and CS1 of device B are connected to CS0 and CS1 of the controller, respectively.
**Figure 1** SPI controller/device connection<a name="fig15227181812587"></a>
- [Figure 1](#fig89085710359) shows the connection between one SPI controller and two SPI devices \(device A and device B\). In this figure, device A and device B share three pins \(SCLK, MISO, and MOSI\) of the controller. CS0 of device A and CS1 of device B are connected to CS0 and CS1 of the controller, respectively.
![](figure/en-us_image_0000001123742254.png)
**Figure 1** SPI controller/device connection<a name="fig89085710359"></a>
![](figures/spi-controller-device-connection.png "spi-controller-device-connection")
- SPI communication is usually initiated by the SPI controller and is operated as follows:
......@@ -54,7 +51,7 @@
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Currently, these functions are only applicable in the communication initiated by the SPI controller.
### Available APIs<a name="section232141411476"></a>
## Available APIs<a name="section1325964832615"></a>
**Table 1** APIs for the SPI driver
......@@ -119,12 +116,10 @@
### How to Use<a name="section32846814820"></a>
[Figure 2](#fig23885455594) shows the process of using an SPI device.
**Figure 2** Process of using an SPI device<a name="fig23885455594"></a>
[Figure 2](#fig1586912310348) shows the process of using an SPI device.
![](figure/en-us_image_0000001123703482.png)
**Figure 2** Process of using an SPI device<a name="fig1586912310348"></a>
![](figures/process-of-using-an-spi-device.png "process-of-using-an-spi-device")
### Obtaining an SPI Device Handle<a name="section1927265711481"></a>
......
# SPI<a name="EN-US_TOPIC_0000001199690327"></a>
- [Overview](#section84922229152909)
- [How to Develop](#section799667984152909)
- [SpiCntlrMethod](#section715682993110)
- [Development Example](#section956157227152909)
## Overview<a name="section84922229152909"></a>
In the Hardware Driver Foundation \(HDF\) framework, the Serial Peripheral Interface \(SPI\) 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.
**Figure 1** Independent service mode<a name="fig666465313303"></a>
![](figures/independent-service-mode-13.png "independent-service-mode-13")
## How to Develop<a name="section799667984152909"></a>
The SPI 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **spi\_config.hcs** file.
3. Instantiate the SPI controller object.
- Initialize **SpiCntlr**.
- Instantiate **SpiCntlrMethod** in the **SpiCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [SpiCntlrMethod](#section715682993110) and [Table 1](#table7167123615321).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the SPI control status and response to interrupts.
### SpiCntlrMethod<a name="section715682993110"></a>
```
struct SpiCntlrMethod {
int32_t (*GetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg);
int32_t (*SetCfg)(struct SpiCntlr *cntlr, struct SpiCfg *cfg);
int32_t (*Transfer)(struct SpiCntlr *cntlr, struct SpiMsg *msg, uint32_t count);
int32_t (*Open)(struct SpiCntlr *cntlr);
int32_t (*Close)(struct SpiCntlr *cntlr);
};
```
**Table 1** Callbacks for the members in the SpiCntlrMethod structure
<a name="table7167123615321"></a>
<table><thead align="left"><tr id="row816783615326"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p8167193643218"><a name="p8167193643218"></a><a name="p8167193643218"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p31672362325"><a name="p31672362325"></a><a name="p31672362325"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="24.98%" id="mcps1.2.5.1.3"><p id="p51673367328"><a name="p51673367328"></a><a name="p51673367328"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="25.019999999999996%" id="mcps1.2.5.1.4"><p id="p1116883619322"><a name="p1116883619322"></a><a name="p1116883619322"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row816883693214"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p11683369329"><a name="p11683369329"></a><a name="p11683369329"></a>Transfer</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p0671913132514"><a name="p0671913132514"></a><a name="p0671913132514"></a><strong id="b19675134258"><a name="b19675134258"></a><a name="b19675134258"></a>cntlr</strong>: structure pointer to the SPI controller at the core layer.</p>
<p id="p192109186258"><a name="p192109186258"></a><a name="p192109186258"></a><strong id="b1921051810258"><a name="b1921051810258"></a><a name="b1921051810258"></a>msg</strong>: structure pointer to the SPI message.</p>
<p id="p6168736173213"><a name="p6168736173213"></a><a name="p6168736173213"></a><strong id="b92627310191"><a name="b92627310191"></a><a name="b92627310191"></a>count</strong>: number of messages. The value is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p19168736113216"><a name="p19168736113216"></a><a name="p19168736113216"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p18168236143218"><a name="p18168236143218"></a><a name="p18168236143218"></a>Transfers messages.</p>
</td>
</tr>
<tr id="row3168113633211"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p4168636193212"><a name="p4168636193212"></a><a name="p4168636193212"></a>SetCfg</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p242632402513"><a name="p242632402513"></a><a name="p242632402513"></a><strong id="b742642452513"><a name="b742642452513"></a><a name="b742642452513"></a>cntlr</strong>: structure pointer to the SPI controller at the core layer.</p>
<p id="p11168163643217"><a name="p11168163643217"></a><a name="p11168163643217"></a><strong id="b1283910558207"><a name="b1283910558207"></a><a name="b1283910558207"></a>cfg</strong>: structure pointer to the SPI attributes.</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p101683367325"><a name="p101683367325"></a><a name="p101683367325"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p1216815368329"><a name="p1216815368329"></a><a name="p1216815368329"></a>Sets SPI controller attributes.</p>
</td>
</tr>
<tr id="row13168183683215"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p11168436123220"><a name="p11168436123220"></a><a name="p11168436123220"></a>GetCfg</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p9698153182520"><a name="p9698153182520"></a><a name="p9698153182520"></a><strong id="b19698131162510"><a name="b19698131162510"></a><a name="b19698131162510"></a>cntlr</strong>: structure pointer to the SPI controller at the core layer.</p>
<p id="p3168936133218"><a name="p3168936133218"></a><a name="p3168936133218"></a><strong id="b11555148182113"><a name="b11555148182113"></a><a name="b11555148182113"></a>cfg</strong>: structure pointer to the SPI attributes.</p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p18169036193219"><a name="p18169036193219"></a><a name="p18169036193219"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p3169136173219"><a name="p3169136173219"></a><a name="p3169136173219"></a>Obtains SPI controller attributes.</p>
</td>
</tr>
<tr id="row9169133643218"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p13169163615320"><a name="p13169163615320"></a><a name="p13169163615320"></a>Open</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p181697365327"><a name="p181697365327"></a><a name="p181697365327"></a><strong id="b1876822162218"><a name="b1876822162218"></a><a name="b1876822162218"></a>cntlr</strong>: structure pointer to the SPI controller at the core layer. </p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p1169163693216"><a name="p1169163693216"></a><a name="p1169163693216"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p1116963693218"><a name="p1116963693218"></a><a name="p1116963693218"></a>Enables the SPI.</p>
</td>
</tr>
<tr id="row11169436153214"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p0169736153219"><a name="p0169736153219"></a><a name="p0169736153219"></a>Close</p>
</td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p31691936193210"><a name="p31691936193210"></a><a name="p31691936193210"></a><strong id="b16798152112239"><a name="b16798152112239"></a><a name="b16798152112239"></a>cntlr</strong>: structure pointer to the SPI controller at the core layer. </p>
</td>
<td class="cellrowborder" valign="top" width="24.98%" headers="mcps1.2.5.1.3 "><p id="p2169123617322"><a name="p2169123617322"></a><a name="p2169123617322"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="25.019999999999996%" headers="mcps1.2.5.1.4 "><p id="p1169636103220"><a name="p1169636103220"></a><a name="p1169636103220"></a>Disables the SPI.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section956157227152909"></a>
The following uses **spi\_hi35xx.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 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.
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.
- SPI driver entry reference
```
struct HdfDriverEntry g_hdfSpiDevice = {
.moduleVersion = 1,
.moduleName = "HDF_PLATFORM_SPI",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.Bind = HdfSpiDeviceBind, // See the Bind function.
.Init = HdfSpiDeviceInit, // See the Init function.
.Release = HdfSpiDeviceRelease, //See the Release function.
};
// Call HDF_INIT to register the driver entry with the HDF framework.
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. 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.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_spi :: device {// Configure an HDF device node for each SPI controller.
device0 :: deviceNode {
policy = 1;
priority = 60;
permission = 0644;
moduleName = "HDF_PLATFORM_SPI";
serviceName = "HDF_PLATFORM_SPI_0";
deviceMatchAttr = "hisilicon_hi35xx_spi_0";
}
device1 :: deviceNode {
policy = 1;
priority = 60;
permission = 0644;
moduleName = "HDF_PLATFORM_SPI"; // (Mandatory) Driver name, which must be the same as that of moduleName in the driver entry structure.
serviceName = "HDF_PLATFORM_SPI_1"; // (Mandatory) Unique name of the service published by the driver
deviceMatchAttr = "hisilicon_hi35xx_spi_1";// The value must be the same as that of match_attr in the .hcs file.
}
...
}
}
}
}
```
- **spi\_config.hcs** configuration reference
```
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 service nodes.
serviceName = "";
match_attr = "";
transferMode = 0; // Data transfer mode, which can be interrupt transfer (0), flow control transfer (1), or DMA transfer (2).
busNum = 0; // Bus number
clkRate = 100000000;
bitsPerWord = 8; // Bit width of the data transferred
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; // Interruption number
REG_CRG_SPI = 0x120100e4; // CRG_REG_BASE(0x12010000) + 0x0e4
CRG_SPI_CKEN = 0;
CRG_SPI_RST = 0;
REG_MISC_CTRL_SPI = 0x12030024; // MISC_REG_BASE(0x12030000) + 0x24
MISC_CTRL_SPI_CS = 0;
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
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 {
busNum = 1;
CRG_SPI_CKEN = 0x20000; // (0x1 << 17) 0:close clk, 1:open clk
CRG_SPI_RST = 0x2; // (0x1 << 1) 0:cancel reset, 1:reset
match_attr = "hisilicon_hi35xx_spi_1";
regBase = 0x120c1000; // (Mandatory) Used for address mapping.
irqNum = 101; // (Mandatory) Interrupt number
}
...
//(Optional) Add nodes to the device_info.hcs file as required.
}
}
}
```
3. Initialize the **SpiCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **SpiCntlrMethod** \(used to call underlying functions of the driver\) in **SpiCntlr**, 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 **spi\_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 object at the core layer.
```
struct Pl022 {// Corresponds to parameters in .hcs.
struct SpiCntlr *cntlr;
struct DListHead deviceList;
struct OsalSem sem;
volatile unsigned char *phyBase;
volatile unsigned char *regBase;
uint32_t irqNum;
uint32_t busNum;
uint32_t numCs;
uint32_t curCs;
uint32_t speed;
uint32_t fifoSize;
uint32_t clkRate;
uint32_t maxSpeedHz;
uint32_t minSpeedHz;
uint32_t regCrg;
uint32_t clkEnBit;
uint32_t clkRstBit;
uint32_t regMiscCtrl;
uint32_t miscCtrlCsShift;
uint32_t miscCtrlCs;
uint16_t mode;
uint8_t bitsPerWord;
uint8_t transferMode;
};
// SpiCntlr is the core layer controller structure. Its members are assigned with values by using the Init function.
struct SpiCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
uint32_t busNum;
uint32_t numCs;
uint32_t curCs;
struct OsalMutex lock;
struct SpiCntlrMethod *method;
struct DListHead list;
void *priv;
};
```
- Instantiate the callback function structure **SpiCntlrMethod** in **SpiCntlr**. Other members are initialized by using the **Init** function.
```
// Example in spi_hi35xx.c: instantiate the hook.
struct SpiCntlrMethod g_method = {
.Transfer = Pl022Transfer,
.SetCfg = Pl022SetCfg,
.GetCfg = Pl022GetCfg,
.Open = Pl022Open,
.Close = Pl022Close,
};
```
- Bind function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS
Function description:
Associates the **SpiCntlr** object with **HdfDeviceObject**.
```
static int32_t HdfSpiDeviceBind(struct HdfDeviceObject *device)
{
...
return (SpiCntlrCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;
}
struct SpiCntlr *SpiCntlrCreate(struct HdfDeviceObject *device)
{
struct SpiCntlr *cntlr = NULL; // Create the SpiCntlr object of the core layer.
...
cntlr = (struct SpiCntlr *)OsalMemCalloc(sizeof(*cntlr));// Allocate memory.
...
cntlr->device = device; // Enable conversion between HdfDeviceObject and SpiCntlr.
device->service = &(cntlr->service); // Enable conversion between HdfDeviceObject and SpiCntlr.
(void)OsalMutexInit(&cntlr->lock); // Initialize the lock.
DListHeadInit(&cntlr->list); // Add the corresponding node.
cntlr->priv = NULL;
return cntlr;
}
```
- Init 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 init function
<a name="table4311552173914"></a>
<table><thead align="left"><tr id="row8314152103916"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p331413523392"><a name="p331413523392"></a><a name="p331413523392"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p7314145220390"><a name="p7314145220390"></a><a name="p7314145220390"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row93142052183918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p93141252123914"><a name="p93141252123914"></a><a name="p93141252123914"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p331485215390"><a name="p331485215390"></a><a name="p331485215390"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row331445211399"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p83141352183917"><a name="p83141352183917"></a><a name="p83141352183917"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p15314175220397"><a name="p15314175220397"></a><a name="p15314175220397"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row20314175213918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p9314352113917"><a name="p9314352113917"></a><a name="p9314352113917"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p131535273910"><a name="p131535273910"></a><a name="p131535273910"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1431565233911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p0315052103915"><a name="p0315052103915"></a><a name="p0315052103915"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1831585215398"><a name="p1831585215398"></a><a name="p1831585215398"></a>I/O error</p>
</td>
</tr>
<tr id="row2315152193914"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p7315185263919"><a name="p7315185263919"></a><a name="p7315185263919"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1731585213910"><a name="p1731585213910"></a><a name="p1731585213910"></a>Initialization successful</p>
</td>
</tr>
<tr id="row5315752163916"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p6315105211392"><a name="p6315105211392"></a><a name="p6315105211392"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p83157528399"><a name="p83157528399"></a><a name="p83157528399"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **SpiCntlr**.
```
static int32_t HdfSpiDeviceInit(struct HdfDeviceObject *device)
{
int32_t ret;
struct SpiCntlr *cntlr = NULL;
...
cntlr = SpiCntlrFromDevice(device);// Forcibly convert HdfDeviceObject to SpiCntlr by 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 = Pl022Probe(cntlr->priv);
...
return ret;
}
static int32_t Pl022Init(struct SpiCntlr *cntlr, const struct HdfDeviceObject *device)
{
int32_t ret;
struct Pl022 *pl022 = NULL;
...
pl022 = (struct Pl022 *)OsalMemCalloc(sizeof(*pl022));// Apply for memory.
...
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.
...
// Calculate the frequencies corresponding to the maximum and minimum speeds.
pl022->maxSpeedHz = (pl022->clkRate) / ((SCR_MIN + 1) * CPSDVSR_MIN);
pl022->minSpeedHz = (pl022->clkRate) / ((SCR_MAX + 1) * CPSDVSR_MAX);
DListHeadInit(&pl022->deviceList);// Initialize the DList linked list.
pl022->cntlr = cntlr; // Enable conversion between Pl022 and SpiCntlr.
cntlr->priv = pl022; // Enable conversion between Pl022 and SpiCntlr.
cntlr->busNum = pl022->busNum; // Assign a value to busNum in SpiCntlr.
cntlr->method = &g_method; // Connect to the SpiCntlrMethod instance.
...
ret = Pl022CreatAndInitDevice(pl022);
if (ret != 0) {
Pl022Release(pl022); // Release the Pl022 object if the initialization fails.
return ret;
}
return 0;
}
```
- 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 framework 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.
```
static void HdfSpiDeviceRelease(struct HdfDeviceObject *device)
{
struct SpiCntlr *cntlr = NULL;
...
cntlr = SpiCntlrFromDevice(device);// Forcibly convert HdfDeviceObject to SpiCntlr by using service. 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.
}
SpiCntlrDestroy(cntlr); // Release the Pl022 object.
}
```
# UART<a name="EN-US_TOPIC_0000001052215244"></a>
# UART<a name="EN-US_TOPIC_0000001160652800"></a>
- [Overview](#section833012453535)
- [Available APIs](#section1680292311549)
- [Available APIs](#section1928742202715)
- [Usage Guidelines](#section12779050105412)
- [How to Use](#section1858116395510)
- [Obtaining a UART Device Handle](#section124512065617)
......@@ -21,27 +20,23 @@
- 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](#fig209936401896)\) or four wires \(as shown in [Figure 2](#fig1435614171015)\).
- 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="fig209936401896"></a>
![](figure/en-us_image_0000001170262141.png)
**Figure 2** 4-wire UART communication<a name="fig1435614171015"></a>
**Figure 1** 2-wire UART communication<a name="fig68294715408"></a>
![](figures/2-wire-uart-communication.png "2-wire-uart-communication")
![](figure/en-us_image_0000001123582482.png)
**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.
- 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<a name="section1680292311549"></a>
## Available APIs<a name="section1928742202715"></a>
**Table 1** APIs for the UART driver
......@@ -122,12 +117,10 @@
### How to Use<a name="section1858116395510"></a>
[Figure 3](#fig1852173020185) shows the process of using a UART device.
**Figure 3** Process of using a UART device<a name="fig1852173020185"></a>
[Figure 3](#fig99673244388) shows the process of using a UART device.
![](figure/en-us_image_0000001170227689.png)
**Figure 3** Process of using a UART device<a name="fig99673244388"></a>
![](figures/process-of-using-a-uart-device.png "process-of-using-a-uart-device")
### Obtaining a UART Device Handle<a name="section124512065617"></a>
......
# UART<a name="EN-US_TOPIC_0000001153656474"></a>
- [Overview](#section1761881586154520)
- [How to Develop](#section944397404154520)
- [UartHostMethod](#section192316441461)
- [Development Example](#section774610224154520)
## Overview<a name="section1761881586154520"></a>
In the Hardware Driver Foundation \(HDF\) framework, the Universal Asynchronous Receiver/Transmitter \(UART\) 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 HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
**Figure 1** Independent service mode<a name="fig1474518243468"></a>
![](figures/independent-service-mode-14.png "independent-service-mode-14")
## How to Develop<a name="section944397404154520"></a>
The UART 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **uart\_config.hcs** file.
3. Instantiate the UART controller object.
- Initialize **UartHost**.
- Instantiate **UartHostMethod** in the **UartHost** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [UartHostMethod](#section192316441461) and [Table 1](#table22862114719).
4. Debug the driver.
- \(Optional\) For new drivers, verify the basic functions, such as the UART control status and response to interrupts.
### UartHostMethod<a name="section192316441461"></a>
```
struct UartHostMethod {
int32_t (*Init)(struct UartHost *host);
int32_t (*Deinit)(struct UartHost *host);
int32_t (*Read)(struct UartHost *host, uint8_t *data, uint32_t size);
int32_t (*Write)(struct UartHost *host, uint8_t *data, uint32_t size);
int32_t (*GetBaud)(struct UartHost *host, uint32_t *baudRate);
int32_t (*SetBaud)(struct UartHost *host, uint32_t baudRate);
int32_t (*GetAttribute)(struct UartHost *host, struct UartAttribute *attribute);
int32_t (*SetAttribute)(struct UartHost *host, struct UartAttribute *attribute);
int32_t (*SetTransMode)(struct UartHost *host, enum UartTransMode mode);
int32_t (*pollEvent)(struct UartHost *host, void *filep, void *table);
};
```
**Table 1** Callbacks for the members in the UartHostMethod structure
<a name="table22862114719"></a>
<table><thead align="left"><tr id="row5297211471"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p12291121134710"><a name="p12291121134710"></a><a name="p12291121134710"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p3291921164712"><a name="p3291921164712"></a><a name="p3291921164712"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="19.98%" id="mcps1.2.6.1.3"><p id="p15291321114718"><a name="p15291321114718"></a><a name="p15291321114718"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20.02%" id="mcps1.2.6.1.4"><p id="p03092115478"><a name="p03092115478"></a><a name="p03092115478"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p230172113475"><a name="p230172113475"></a><a name="p230172113475"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row13305217472"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p193012104714"><a name="p193012104714"></a><a name="p193012104714"></a>Init</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p53082134713"><a name="p53082134713"></a><a name="p53082134713"></a><strong id="b231216565514"><a name="b231216565514"></a><a name="b231216565514"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p14301121174719"><a name="p14301121174719"></a><a name="p14301121174719"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p83092116473"><a name="p83092116473"></a><a name="p83092116473"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p173032124713"><a name="p173032124713"></a><a name="p173032124713"></a>Initializes the UART device.</p>
</td>
</tr>
<tr id="row530121144713"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p12301215474"><a name="p12301215474"></a><a name="p12301215474"></a>Deinit</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p14301921174718"><a name="p14301921174718"></a><a name="p14301921174718"></a><strong id="b7500154935512"><a name="b7500154935512"></a><a name="b7500154935512"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p143142110477"><a name="p143142110477"></a><a name="p143142110477"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p1531162174719"><a name="p1531162174719"></a><a name="p1531162174719"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p203162110478"><a name="p203162110478"></a><a name="p203162110478"></a>Deinitializes the UART device.</p>
</td>
</tr>
<tr id="row93172118476"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1231102194712"><a name="p1231102194712"></a><a name="p1231102194712"></a>Read</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p117841019115819"><a name="p117841019115819"></a><a name="p117841019115819"></a><strong id="b8784519205820"><a name="b8784519205820"></a><a name="b8784519205820"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
<p id="p13318214472"><a name="p13318214472"></a><a name="p13318214472"></a><strong id="b76471214185712"><a name="b76471214185712"></a><a name="b76471214185712"></a>size</strong>: data size, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p1313213473"><a name="p1313213473"></a><a name="p1313213473"></a><strong id="b1372195311577"><a name="b1372195311577"></a><a name="b1372195311577"></a>data</strong>: uint8_t pointer to the output data.</p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p193110216473"><a name="p193110216473"></a><a name="p193110216473"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1331102115475"><a name="p1331102115475"></a><a name="p1331102115475"></a>Receives data.</p>
</td>
</tr>
<tr id="row1731102120479"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p731321204711"><a name="p731321204711"></a><a name="p731321204711"></a>Write</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p11377332105815"><a name="p11377332105815"></a><a name="p11377332105815"></a><strong id="b193771532135811"><a name="b193771532135811"></a><a name="b193771532135811"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
<p id="p174031635125817"><a name="p174031635125817"></a><a name="p174031635125817"></a><strong id="b540373505819"><a name="b540373505819"></a><a name="b540373505819"></a>data</strong>: pointer to the input data, which is of the uint8_t type.</p>
<p id="p15311321204719"><a name="p15311321204719"></a><a name="p15311321204719"></a><strong id="b15686191305911"><a name="b15686191305911"></a><a name="b15686191305911"></a>size</strong>: data size, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p143142114478"><a name="p143142114478"></a><a name="p143142114478"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p143212110477"><a name="p143212110477"></a><a name="p143212110477"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p123216211477"><a name="p123216211477"></a><a name="p123216211477"></a>Sends data.</p>
</td>
</tr>
<tr id="row73215214478"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1032112119475"><a name="p1032112119475"></a><a name="p1032112119475"></a>SetBaud</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p863959125812"><a name="p863959125812"></a><a name="p863959125812"></a><strong id="b11631159145818"><a name="b11631159145818"></a><a name="b11631159145818"></a>host</strong>: structure pointer to the UART controller at the core layer. </p>
<p id="p3321521134717"><a name="p3321521134717"></a><a name="p3321521134717"></a><strong id="b16745461412"><a name="b16745461412"></a><a name="b16745461412"></a>baudRate</strong>: pointer to the input baud rate, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p18327218478"><a name="p18327218478"></a><a name="p18327218478"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p23242111475"><a name="p23242111475"></a><a name="p23242111475"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p7321521114711"><a name="p7321521114711"></a><a name="p7321521114711"></a>Sets the baud rate.</p>
</td>
</tr>
<tr id="row113252104713"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p9323219476"><a name="p9323219476"></a><a name="p9323219476"></a>GetBaud</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p132821184711"><a name="p132821184711"></a><a name="p132821184711"></a><strong id="b4510164912550"><a name="b4510164912550"></a><a name="b4510164912550"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p63262112477"><a name="p63262112477"></a><a name="p63262112477"></a><strong id="b1097116311227"><a name="b1097116311227"></a><a name="b1097116311227"></a>baudRate</strong>: uint32_t pointer to the output baud rate.</p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p13262174719"><a name="p13262174719"></a><a name="p13262174719"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p163232154717"><a name="p163232154717"></a><a name="p163232154717"></a>Obtains the current baud rate.</p>
</td>
</tr>
<tr id="row2032102118472"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p9331321154714"><a name="p9331321154714"></a><a name="p9331321154714"></a>GetAttribute</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p15331721164715"><a name="p15331721164715"></a><a name="p15331721164715"></a><strong id="b1518144935510"><a name="b1518144935510"></a><a name="b1518144935510"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p23313219472"><a name="p23313219472"></a><a name="p23313219472"></a><strong id="b16392039333"><a name="b16392039333"></a><a name="b16392039333"></a>attribute</strong>: structure pointer to the output attributes. For details, see <strong id="b524111513416"><a name="b524111513416"></a><a name="b524111513416"></a>UartAttribute</strong> in <strong id="b47291920444"><a name="b47291920444"></a><a name="b47291920444"></a>uart_if.h</strong>.</p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p833142115476"><a name="p833142115476"></a><a name="p833142115476"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p63342119476"><a name="p63342119476"></a><a name="p63342119476"></a>Obtains UART attributes.</p>
</td>
</tr>
<tr id="row1133112144717"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p14331421114715"><a name="p14331421114715"></a><a name="p14331421114715"></a>SetAttribute</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p147011110590"><a name="p147011110590"></a><a name="p147011110590"></a><strong id="b070151125915"><a name="b070151125915"></a><a name="b070151125915"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
<p id="p16331210473"><a name="p16331210473"></a><a name="p16331210473"></a><strong id="b1497919522420"><a name="b1497919522420"></a><a name="b1497919522420"></a>attribute</strong>: structure pointer to the input attributes.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p3331721204710"><a name="p3331721204710"></a><a name="p3331721204710"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p03302111471"><a name="p03302111471"></a><a name="p03302111471"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p1933152113478"><a name="p1933152113478"></a><a name="p1933152113478"></a>Sets UART attributes.</p>
</td>
</tr>
<tr id="row834221114716"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1934821104719"><a name="p1934821104719"></a><a name="p1934821104719"></a>SetTransMode</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1821251985919"><a name="p1821251985919"></a><a name="p1821251985919"></a><strong id="b1121271918594"><a name="b1121271918594"></a><a name="b1121271918594"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
<p id="p1034621104717"><a name="p1034621104717"></a><a name="p1034621104717"></a><strong id="b104767219711"><a name="b104767219711"></a><a name="b104767219711"></a>mode</strong>: transmission mode, which is an enumerated value. For details, see <strong id="b2101455871"><a name="b2101455871"></a><a name="b2101455871"></a>UartTransMode</strong> in <strong id="b99657016815"><a name="b99657016815"></a><a name="b99657016815"></a>uart_if.h</strong>).</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p173442110475"><a name="p173442110475"></a><a name="p173442110475"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p1734721194720"><a name="p1734721194720"></a><a name="p1734721194720"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p15341021194715"><a name="p15341021194715"></a><a name="p15341021194715"></a>Sets the UART transmission mode.</p>
</td>
</tr>
<tr id="row434192119479"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p133442184717"><a name="p133442184717"></a><a name="p133442184717"></a>PollEvent</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p31278367592"><a name="p31278367592"></a><a name="p31278367592"></a><strong id="b1127163625919"><a name="b1127163625919"></a><a name="b1127163625919"></a>host</strong>: structure pointer to the UART controller at the core layer.</p>
<p id="p16654144015591"><a name="p16654144015591"></a><a name="p16654144015591"></a><strong id="b86541440135917"><a name="b86541440135917"></a><a name="b86541440135917"></a>filep</strong>: void pointer to a file.</p>
<p id="p634121104712"><a name="p634121104712"></a><a name="p634121104712"></a><strong id="b163481035141514"><a name="b163481035141514"></a><a name="b163481035141514"></a>table</strong>: void pointer to a poll_table.</p>
</td>
<td class="cellrowborder" valign="top" width="19.98%" headers="mcps1.2.6.1.3 "><p id="p1334142111479"><a name="p1334142111479"></a><a name="p1334142111479"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20.02%" headers="mcps1.2.6.1.4 "><p id="p133472110473"><a name="p133472110473"></a><a name="p133472110473"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p63522174720"><a name="p63522174720"></a><a name="p63522174720"></a>Polls for pending events.</p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section774610224154520"></a>
The following uses **uart\_hi35xx.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 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.
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.
- UART driver entry reference
```
struct HdfDriverEntry g_hdfUartDevice = {
.moduleVersion = 1,
.moduleName = "HDF_PLATFORM_UART", // (Mandatory) This parameter must be the same as that in the .hcs file.
.Bind = HdfUartDeviceBind, // See the Bind function.
.Init = HdfUartDeviceInit, // See the Init function.
.Release = HdfUartDeviceRelease, //See the Release function.
};
// Call HDF_INIT to register the driver entry with the HDF framework.
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. 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.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_uart :: device {
device0 :: deviceNode {
policy = 1; // The value 1 indicates that the driver publishes kernel-mode services. The value 2 indicates that the driver publishes user-mode services.
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 that of moduleName in the driver entry 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 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 {
policy = 2;
permission = 0644;
priority = 40;
moduleName = "HDF_PLATFORM_UART";
serviceName = "HDF_PLATFORM_UART_1";
deviceMatchAttr = "hisilicon_hi35xx_uart_1";
}
...
}
}
}
}
```
- **uart\_config.hcs** configuration reference
```
root {
platform {
template uart_controller {// Template configuration. In the template, you can configure the common parameters shared by service nodes.
match_attr = "";
num = 0; // (Mandatory) Device number
baudrate = 115200; // (Mandatory) Baud rate. Set the value based on service requirements.
fifoRxEn = 1; // (Mandatory) Enable the receive of FIFOs.
fifoTxEn = 1; // (Mandatory) Enable the transmit of FIFOs.
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.
}
controller_0x120a1000 :: uart_controller {
num = 1;
baudrate = 9600;
regPbase = 0x120a1000;
interrupt = 39;
match_attr = "hisilicon_hi35xx_uart_1";
}
...
//(Optional) Add nodes to the device_info.hcs file as required.
}
}
```
3. Initialize the **UartHost** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **UartHostMethod** \(used to call underlying functions of the driver\) in **UartHost**, 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 **uart\_config.hcs** file are read by HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the device number, are also passed to the objects at the core layer.
```
struct UartPl011Port {// Structure related to the API
int32_t enable;
unsigned long physBase; // Physical address
uint32_t irqNum; // Interrupt number
uint32_t defaultBaudrate;// Default baud rate
uint32_t flags; // Flag signal, which is 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 transmission
struct UartDriverData *udd; // See the following description.
};
struct UartDriverData {// Structure related to data transmission
uint32_t num;
uint32_t baudrate; // Baud rate (configurable)
struct UartAttribute attr; // Transmission attributes, such as the data bit and stop bit
struct UartTransfer *rxTransfer; // FIFO structure related to the buffer
wait_queue_head_t wait; // Queuing signal related to conditional variables
int32_t count; // Data count
int32_t state; // UART controller status
#define UART_STATE_NOT_OPENED 0
#define UART_STATE_OPENING 1
#define UART_STATE_USEABLE 2
#define UART_STATE_SUSPENED 3
uint32_t flags; // Status flag
#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 start address of UartPl011Port for easy invocation.
};
// UartHost is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct UartHost {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
uint32_t num;
OsalAtomic atom;
void *priv; // It stores the start address of the vendor's custom structure for invoking the structure.
struct UartHostMethod *method; // Hook at the core layer. The vendor needs to implement and instantiate its member functions.
};
```
- Instantiate the callback function structure **UartHostMethod** in **UartHost**. Other members are initialized by using the **Bind** function.
```
// Example in pwm_hi35xx.c: instantiate the hook.
struct UartHostMethod g_uartHostMethod = {
.Init = Hi35xxInit,
.Deinit = Hi35xxDeinit,
.Read = Hi35xxRead,
.Write = Hi35xxWrite,
.SetBaud = Hi35xxSetBaud,
.GetBaud = Hi35xxGetBaud,
.SetAttribute = Hi35xxSetAttribute,
.GetAttribute = Hi35xxGetAttribute,
.SetTransMode = Hi35xxSetTransMode,
.pollEvent = Hi35xxPollEvent,
};
```
- 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="table69781823185619"></a>
<table><thead align="left"><tr id="row997916234569"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p99801123205616"><a name="p99801123205616"></a><a name="p99801123205616"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p698092355615"><a name="p698092355615"></a><a name="p698092355615"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row39803236568"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p8980123175613"><a name="p8980123175613"></a><a name="p8980123175613"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p79801423165611"><a name="p79801423165611"></a><a name="p79801423165611"></a>Invalid controller object</p>
</td>
</tr>
<tr id="row3980023165617"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p698011239568"><a name="p698011239568"></a><a name="p698011239568"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p798082395610"><a name="p798082395610"></a><a name="p798082395610"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row10980223165610"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1980172365614"><a name="p1980172365614"></a><a name="p1980172365614"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p14980223145614"><a name="p14980223145614"></a><a name="p14980223145614"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row7980142315612"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p17980152385611"><a name="p17980152385611"></a><a name="p17980152385611"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p17980182385611"><a name="p17980182385611"></a><a name="p17980182385611"></a>I/O error</p>
</td>
</tr>
<tr id="row9980122312564"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p10981323155616"><a name="p10981323155616"></a><a name="p10981323155616"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p11981423175614"><a name="p11981423175614"></a><a name="p11981423175614"></a>Initialization successful</p>
</td>
</tr>
<tr id="row15981122365618"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p19981122311567"><a name="p19981122311567"></a><a name="p19981122311567"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p199811723105615"><a name="p199811723105615"></a><a name="p199811723105615"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **UartHost**.
```
//uart_hi35xx.c
static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device)
{
...
return (UartHostCreate(device) == NULL)? HDF_FAILURE: HDF_SUCCESS;// (Mandatory) Call UartHostCreate.
}
// Description of the UartHostCreate function at the core layer in uart_core.c
struct UartHost *UartHostCreate(struct HdfDeviceObject *device)
{
struct UartHost *host = NULL; // Create a UartHost.
...
host = (struct UartHost *)OsalMemCalloc(sizeof(*host));// Apply for memory.
...
host->device = device; // (Mandatory) Enable conversion between HdfDeviceObject and UartHost.
device->service = &(host->service); // (Mandatory) Enable conversion between HdfDeviceObject and UartHost.
host->device->service->Dispatch = UartIoDispatch;// Assign a value to the Dispatch method of service.
OsalAtomicSet(&host->atom, 0); // Initialize or set atomic data.
host->priv = NULL;
host->method = NULL;
return host;
}
```
- Init function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return values:
HDF\_STATUS
Function description:
Initializes the custom structure object and **UartHost**, calls the **artAddDev** function at the core layer, and connects to VFS.
```
int32_t HdfUartDeviceInit(struct HdfDeviceObject *device)
{
int32_t ret;
struct UartHost *host = NULL;
HDF_LOGI("%s: entry", __func__);
...
host = UartHostFromDevice(device);// Forcibly convert to UartHost by using service. The value is assigned in the Bind function.
...
ret = Hi35xxAttach(host, device); // Initialize the UartHost object.
...
host->method = &g_uartHostMethod; // Connect to the UARTHostMethod instance.
return ret;
}
// Complete initialization of the UartHost object.
static int32_t Hi35xxAttach(struct UartHost *host, struct HdfDeviceObject *device)
{
int32_t ret;
// udd and port are structure objects customized by the vendor. Implement related functions as required.
struct UartDriverData *udd = NULL;
struct UartPl011Port *port = NULL;
...
// Steps [1] to [7] assign values to udd and then to the UartHost object at the core layer.
udd = (struct UartDriverData *)OsalMemCalloc(sizeof(*udd));// [1]
...
port = (struct UartPl011Port *)OsalMemCalloc(sizeof(struct UartPl011Port));// [2]
...
udd->ops = Pl011GetOps();// [3] Perform operations, such as starting or stopping a device, setting attributes, and sending data.
udd->recv = PL011UartRecvNotify;// [4] Connect to the data receiving notification function (conditional lock mechanism).
udd->count = 0; // [5]
port->udd = udd; // [6] Enable conversion between UartPl011Port and UartDriverData.
ret = UartGetConfigFromHcs(port, device->property);// (Mandatory) Transfer the attributes of HdfDeviceObject to the vendor custom structure.
// The sample code is as follows:
...
udd->private = port; // [7]
host->priv = udd; // (Mandatory) Enable conversion between UartHost and UartDriverData.
host->num = udd->num;// (Mandatory) UART device number
UartAddDev(host); // (Mandatory) Function in uart_dev.c at the core layer used to register a character device node with the VFS so that the UART can be accessed in user mode through this virtual file node.
return HDF_SUCCESS;
}
static int32_t UartGetConfigFromHcs(struct UartPl011Port *port, const struct DeviceResourceNode *node)
{
uint32_t tmp, regPbase, iomemCount;
struct UartDriverData *udd = port->udd;
struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
...
// Extract the value based on the request parameter and assign the value to the vendor custom structure.
if (iface->GetUint32(node, "num", &udd->num, 0) != HDF_SUCCESS) {
HDF_LOGE("%s: read busNum fail", __func__);
return HDF_FAILURE;
}
...
return 0;
}
```
- 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 framework 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.
```
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.
...
if (host->priv != NULL) {
Hi35xxDetach(host); // Memory release function customized by the vendor. For details, see the following description.
}
UartHostDestroy(host); // Call the function of the core layer to release the host.
}
static void Hi35xxDetach(struct UartHost *host)
{
struct UartDriverData *udd = NULL;
struct UartPl011Port *port = NULL;
...
udd = host->priv; // Convert UartHost to UartDriverData.
...
UartRemoveDev(host);// Remove the VFS.
port = udd->private;// Convert UartDriverData to UartPl011Port.
if (port != NULL) {
if (port->physBase != 0) {
OsalIoUnmap((void *)port->physBase);// Remove address mapping.
}
(void)OsalMemFree(port);
udd->private = NULL;
}
(void)OsalMemFree(udd);// Release UartDriverData.
host->priv = NULL;
}
```
# Watchdog<a name="EN-US_TOPIC_0000001052935969"></a>
# Watchdog<a name="EN-US_TOPIC_0000001206372825"></a>
- [Overview](#section14918241977)
- [Available APIs](#section20177131219818)
- [Available APIs](#section1180575010271)
- [Usage Guidelines](#section10103184312813)
- [How to Use](#section10181195910815)
- [Opening a Watchdog](#section66089201107)
......@@ -20,7 +19,7 @@
A watchdog, also called a watchdog timer, is a hardware timing device. If an error occurs in the main program of the system and fails to reset the watchdog timer, the watchdog timer sends a reset signal to restore the system to a normal state.
### Available APIs<a name="section20177131219818"></a>
## Available APIs<a name="section1180575010271"></a>
**Table 1** Watchdog APIs
......@@ -93,18 +92,16 @@ A watchdog, also called a watchdog timer, is a hardware timing device. If an err
### How to Use<a name="section10181195910815"></a>
[Figure 1](#fig19134125410189) illustrates the process of using a watchdog.
**Figure 1** Process of using a watchdog<a name="fig19134125410189"></a>
[Figure 1](#fig430533913392) illustrates the process of using a watchdog.
![](figure/en-us_image_0000001170229891.png)
**Figure 1** Process of using a watchdog<a name="fig430533913392"></a>
![](figures/process-of-using-a-watchdog.png "process-of-using-a-watchdog")
### Opening a Watchdog<a name="section66089201107"></a>
Use **WatchdogOpen** to open a watchdog. A system may have multiple watchdogs. You can open the specified watchdog by using the ID.
DevHandle WatchdogOpen\(int16\_t wdtId\);
int32\_t WatchdogOpen\(int16\_t wdtId\);
**Table 2** Description of WatchdogOpen
......@@ -201,7 +198,7 @@ if (ret != 0) {
### Setting the Timeout Duration<a name="section182386137111"></a>
int32\_t WatchdogSetTimeout\(DevHandle \*handle, uint32\_t seconds\);
int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\);
**Table 4** Description of WatchdogSetTimeout
......@@ -253,7 +250,7 @@ if (ret != 0) {
### Obtaining the Timeout Duration<a name="section1883310371114"></a>
int32\_t WatchdogGetTimeout\(DevHandle \*handle, uint32\_t \*seconds\);
int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\);
**Table 5** Description of WatchdogGetTimeout
......
# Watchdog<a name="EN-US_TOPIC_0000001199821009"></a>
- [Overview](#section1315827527160117)
- [How to Develop](#section477974542160117)
- [WatchdogMethod](#section220331929)
- [Development Example](#section1832270347160117)
## Overview<a name="section1315827527160117"></a>
In the Hardware Driver Foundation \(HDF\) framework, the Watchdog \(also called Watchdog timer\) 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 HDF Device Manager can be directly used. However, you need to configure a device node for each device, which increases the memory usage.
**Figure 1** Independent service mode<a name="fig61584136211"></a>
![](figures/independent-service-mode-15.png "independent-service-mode-15")
## How to Develop<a name="section477974542160117"></a>
The Watchdog 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 framework.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **watchdog\_config.hcs** file.
3. Instantiate the Watchdog controller object.
- Initialize **WatchdogCntlr**.
- Instantiate **WatchdogMethod** in the **WatchdogCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [WatchdogMethod](#section220331929) and [Table 1](#table1370451732).
4. Debug the driver.
- \(Optional\) For new drivers, verify basic functions, for example, verify the information returned after the connect operation and whether the watchdog timer is successfully set.
### WatchdogMethod<a name="section220331929"></a>
```
struct WatchdogMethod {
int32_t (*getStatus)(struct WatchdogCntlr *wdt, int32_t *status);
int32_t (*setTimeout)(struct WatchdogCntlr *wdt, uint32_t seconds);
int32_t (*getTimeout)(struct WatchdogCntlr *wdt, uint32_t *seconds);
int32_t (*start)(struct WatchdogCntlr *wdt);
int32_t (*stop)(struct WatchdogCntlr *wdt);
int32_t (*feed)(struct WatchdogCntlr *wdt);
int32_t (*getPriv)(struct WatchdogCntlr *wdt); // (Optional) If WatchdogCntlr has the priv member, instantiate priv.
void (*releasePriv)(struct WatchdogCntlr *wdt);// (Optional)
};
```
**Table 1** Callbacks for the members in the WatchdogMethod structure
<a name="table1370451732"></a>
<table><thead align="left"><tr id="row370511435"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="p170681939"><a name="p170681939"></a><a name="p170681939"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="p870641434"><a name="p870641434"></a><a name="p870641434"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="p27061011739"><a name="p27061011739"></a><a name="p27061011739"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="p10707618315"><a name="p10707618315"></a><a name="p10707618315"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="p37071516316"><a name="p37071516316"></a><a name="p37071516316"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row18707191835"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p970720118311"><a name="p970720118311"></a><a name="p970720118311"></a>getStatus</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p124968261413"><a name="p124968261413"></a><a name="p124968261413"></a><strong id="b13481135102819"><a name="b13481135102819"></a><a name="b13481135102819"></a>wdt</strong>: structure pointer to the Watchdog controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p17071515316"><a name="p17071515316"></a><a name="p17071515316"></a><strong id="b142021397417"><a name="b142021397417"></a><a name="b142021397417"></a>status</strong>: int32_t pointer indicating the watchdog status (started or stopped).</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p5707319312"><a name="p5707319312"></a><a name="p5707319312"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p2707511312"><a name="p2707511312"></a><a name="p2707511312"></a>Obtains the watchdog status.</p>
</td>
</tr>
<tr id="row27071911538"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p370701533"><a name="p370701533"></a><a name="p370701533"></a>start</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p117071316317"><a name="p117071316317"></a><a name="p117071316317"></a><strong id="b136901310133110"><a name="b136901310133110"></a><a name="b136901310133110"></a>wdt</strong>: structure pointer to the Watchdog controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p127071411735"><a name="p127071411735"></a><a name="p127071411735"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p19707111331"><a name="p19707111331"></a><a name="p19707111331"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p170811111319"><a name="p170811111319"></a><a name="p170811111319"></a>Starts a watchdog.</p>
</td>
</tr>
<tr id="row17708191130"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p11708113315"><a name="p11708113315"></a><a name="p11708113315"></a>stop</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p870841138"><a name="p870841138"></a><a name="p870841138"></a><strong id="b14846151912249"><a name="b14846151912249"></a><a name="b14846151912249"></a>wdt</strong>: structure pointer to the Watchdog controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p770841533"><a name="p770841533"></a><a name="p770841533"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p18708115313"><a name="p18708115313"></a><a name="p18708115313"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p3708121738"><a name="p3708121738"></a><a name="p3708121738"></a>Stops a watchdog.</p>
</td>
</tr>
<tr id="row107081818310"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p10708181136"><a name="p10708181136"></a><a name="p10708181136"></a>setTimeout</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p2021212409407"><a name="p2021212409407"></a><a name="p2021212409407"></a><strong id="b1521224016409"><a name="b1521224016409"></a><a name="b1521224016409"></a>wdt</strong>: structure pointer to the Watchdog controller at the core layer.</p>
<p id="p1870801834"><a name="p1870801834"></a><a name="p1870801834"></a><strong id="b721091763217"><a name="b721091763217"></a><a name="b721091763217"></a>seconds</strong>: input time value, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p77081011731"><a name="p77081011731"></a><a name="p77081011731"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p470871436"><a name="p470871436"></a><a name="p470871436"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p57091717315"><a name="p57091717315"></a><a name="p57091717315"></a>Sets the timeout period (in seconds) for a watchdog. Ensure that the actual watchdog running time complies with this setting.</p>
</td>
</tr>
<tr id="row3709911938"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p2070911932"><a name="p2070911932"></a><a name="p2070911932"></a>getTimeout</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p47091711732"><a name="p47091711732"></a><a name="p47091711732"></a><strong id="b88511419192416"><a name="b88511419192416"></a><a name="b88511419192416"></a>wdt</strong>: structure pointer to the Watchdog controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p57091411632"><a name="p57091411632"></a><a name="p57091411632"></a><strong id="b3906135871316"><a name="b3906135871316"></a><a name="b3906135871316"></a>seconds</strong>: output time value, which is of the uint32_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1470941838"><a name="p1470941838"></a><a name="p1470941838"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p17091511139"><a name="p17091511139"></a><a name="p17091511139"></a>Obtains the timeout period of a watchdog.</p>
</td>
</tr>
<tr id="row1770919112319"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="p1270913116313"><a name="p1270913116313"></a><a name="p1270913116313"></a>feed</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p570971736"><a name="p570971736"></a><a name="p570971736"></a><strong id="b1854319172417"><a name="b1854319172417"></a><a name="b1854319172417"></a>wdt</strong>: structure pointer to the Watchdog controller at the core layer.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="p67091517315"><a name="p67091517315"></a><a name="p67091517315"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="p1670915111312"><a name="p1670915111312"></a><a name="p1670915111312"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="p10709818316"><a name="p10709818316"></a><a name="p10709818316"></a>Feeds a watchdog. </p>
</td>
</tr>
</tbody>
</table>
## Development Example<a name="section1832270347160117"></a>
The following uses **watchdog\_hi35xx.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 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.
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.
- Watchdog driver entry reference
```
struct HdfDriverEntry g_watchdogDriverEntry = {
.moduleVersion = 1,
.Bind = Hi35xxWatchdogBind, // See the Bind function.
.Init = Hi35xxWatchdogInit, // See the Init function.
.Release = Hi35xxWatchdogRelease, //See the Release function.
.moduleName = "HDF_PLATFORM_WATCHDOG",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
HDF_INIT(g_watchdogDriverEntry);// Call HDF_INIT to register the driver entry with the HDF framework.
```
2. Add the **deviceNode** information to the **device\_info.hcs** file and configure the component attributes in the **watchdog\_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 **WatchdogCntlr** members at the core layer.
In this example, there is only one Watchdog controller. If there are multiple Watchdog controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **watchdog\_config** file.
- **device\_info.hcs** configuration reference
```
root {
device_info {
match_attr = "hdf_manager";
device_watchdog :: device {// Device node
device0:: deviceNode {// DeviceNode of the driver
The policy = 1; // The value 1 indicates that the driver publishes kernel-mode services. The value 2 indicates that the driver publishes user-mode services.
priority = 20; // Driver startup priority
permission = 0644; // Permission to create device nodes for the driver
moduleName = "HDF_PLATFORM_WATCHDOG";
// (Mandatory) Driver name. The value must be the same as that of moduleName in the driver entry structure.
serviceName = "HDF_PLATFORM_WATCHDOG_0";
// (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "hisilicon_hi35xx_watchdog_0";
// (Mandatory) Keyword 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.
}
}
}
}
```
- **watchdog\_config.hcs** configuration reference
```
root {
platform {
template watchdog_controller {// Template configuration. In the template, you can configure the common parameters shared by service nodes.
id = 0;
match_attr = "";
regBase = 0x12050000; // (Mandatory) Used for address mapping.
regStep = 0x1000; // (Mandatory) Used for address mapping.
}
controller_0x12050000 :: watchdog_controller {// (Mandatory) Keyword for matching the private data of the device driver.
match_attr = "hisilicon_hi35xx_watchdog_0"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
}
// Configure this parameter when there are multiple watchdogs.
...
}
}
```
3. Initialize the **WatchdogCntlr** object at the core layer, including initializing the vendor custom structure \(transferring parameters and data\), instantiating **WatchdogMethod** \(used to call underlying functions of the driver\) in **WatchdogCntlr**, 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 **watchdog\_config.hcs** file are read by the HDF, and the structure members are initialized through **DeviceResourceIface**. Some important values, such as the index and the number of pins, are also transferred to the **WatchdogCntlr** object at the core layer.
```
struct Hi35xxWatchdog {
struct WatchdogCntlr wdt; // (Mandatory) Carrier that connects the upper and underlying layers. For details, see the following description.
OsalSpinlock lock;
volatile unsigned char *regBase;// [Mandatory] Used for address mapping.
uint32_t phyBase; // (Mandatory) Used for address mapping.
uint32_t regStep; // (Mandatory) Used for address mapping.
};
// WatchdogCntlr is the core layer controller structure. Its members are assigned with values by using the Init function.
struct WatchdogCntlr {
struct IDeviceIoService service;// Driver service
struct HdfDeviceObject *device; // Drive device
OsalSpinlock lock; // This variable implements the spinlock function.
struct WatchdogMethod *ops; // Interface callback
int16_t wdtId; // ID of the watchdog device
void *priv; // Save the pointer.
};
```
- Instantiate the callback function structure **WatchdogMethod** in **WatchdogCntlr**. Other members are initialized by using the **Init** and **Bind** functions.
```
static struct WatchdogMethod g_method = {
.getStatus = Hi35xxWatchdogGetStatus,
.start = Hi35xxWatchdogStart,
.stop = Hi35xxWatchdogStop,
.setTimeout = Hi35xxWatchdogSetTimeout,
.getTimeout = Hi35xxWatchdogGetTimeout,
.feed = Hi35xxWatchdogFeed,
};
```
- Init and Bind functions
Input parameters:
**HdfDeviceObject**: device object created by the HDF framework for each driver. It stores device-related private data and service APIs.
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 Init and Bind functions
<a name="table86931033998"></a>
<table><thead align="left"><tr id="row10694203319911"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p1669433319918"><a name="p1669433319918"></a><a name="p1669433319918"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p06945331911"><a name="p06945331911"></a><a name="p06945331911"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row869417338918"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p96941433391"><a name="p96941433391"></a><a name="p96941433391"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p4694333395"><a name="p4694333395"></a><a name="p4694333395"></a>Failed to locate the watchdog device</p>
</td>
</tr>
<tr id="row136941833091"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p66941336920"><a name="p66941336920"></a><a name="p66941336920"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1694133395"><a name="p1694133395"></a><a name="p1694133395"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row469443317913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p116951933293"><a name="p116951933293"></a><a name="p116951933293"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p969511331918"><a name="p969511331918"></a><a name="p969511331918"></a>I/O error</p>
</td>
</tr>
<tr id="row369533318911"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p669511331891"><a name="p669511331891"></a><a name="p669511331891"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p136951233699"><a name="p136951233699"></a><a name="p136951233699"></a>Initialization successful</p>
</td>
</tr>
<tr id="row17695633596"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1469583314910"><a name="p1469583314910"></a><a name="p1469583314910"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p10695193311919"><a name="p10695193311919"></a><a name="p10695193311919"></a>Initialization failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Initializes the custom structure object and **WatchdogCntlr**, and calls the **WatchdogCntlrAdd** function at the core layer.
```
// Generally, the Init function initializes the members of the Hi35xxWatchdog structure based on the attribute values of the input parameter (HdfDeviceObject).
// In this example, the Bind function initializes the Hi35xxWatchdog structure.
static int32_t Hi35xxWatchdogInit(struct HdfDeviceObject *device)
{
(void)device;
return HDF_SUCCESS;
}
static int32_t Hi35xxWatchdogBind(struct HdfDeviceObject *device)
{
int32_t ret;
struct Hi35xxWatchdog *hwdt = NULL;
...
hwdt = (struct Hi35xxWatchdog *)OsalMemCalloc(sizeof(*hwdt));// Apply for memory for the Hi35xxWatchdog structure.
...
hwdt->regBase = OsalIoRemap(hwdt->phyBase, hwdt->regStep); // Address mapping
...
hwdt->wdt.priv = (void *)device->property;// (Optional) Assign the device attribute values to priv. However, priv is not called subsequently.
//If priv needs to be called, instantiate the getPriv and releasePriv member functions in WatchdogMethod.
hwdt->wdt.ops = &g_method; // (Mandatory) Assign the instantiated objects to the ops member so that the top layer can invoke the WatchdogMethod member functions.
hwdt->wdt.device = device; // (Mandatory) Enable conversion between HdfDeviceObject and WatchdogcCntlr.
ret = WatchdogCntlrAdd(&hwdt->wdt); // (Mandatory) Call this function to initialize the structure of the core layer. The driver accesses the platform core layer only after a success signal is returned.
if (ret != HDF_SUCCESS) {// If the operation fails, release the resources used by the Init function.
OsalIoUnmap((void *)hwdt->regBase);
OsalMemFree(hwdt);
return ret;
}
return HDF_SUCCESS;
}
```
- Release function
Input parameters:
**HdfDeviceObject**: device object created by the HDF framework for each driver. It stores device-related private data and service APIs.
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 framework 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.
```
static void Hi35xxWatchdogRelease(struct HdfDeviceObject *device)
{
struct WatchdogCntlr *wdt = NULL;
struct Hi35xxWatchdog *hwdt = NULL;
...
wdt = WatchdogCntlrFromDevice(device);// Convert HdfDeviceObject to WatchdogCntlr by the service member.
//return (device == NULL) ? NULL : (struct WatchdogCntlr *)device->service;
if (wdt == NULL) {
return;
}
WatchdogCntlrRemove(wdt); // Core layer function used to execute wdt->device->service = NULL and release cntlr->lock.
hwdt = (struct Hi35xxWatchdog *)wdt; // Convert WatchdogCntlr to HimciHost.
if (hwdt->regBase != NULL) {// Remove address mapping.
OsalIoUnmap((void *)hwdt->regBase);
hwdt->regBase = NULL;
}
OsalMemFree(hwdt); // Release the memory occupied by the vendor-defined objects.
}
```
# Platform Drivers<a name="EN-US_TOPIC_0000001111199424"></a>
# Platform Driver Usage<a name="EN-US_TOPIC_0000001111199424"></a>
- **[GPIO](driver-platform-gpio-des.md)**
......@@ -16,4 +16,6 @@
- **[MIPI DSI](driver-platform-mipidsi-des.md)**
- **[PWM](driver-platform-pwm-des.md)**
# Driver Usage Guidelines<a name="EN-US_TOPIC_0000001111039544"></a>
# Drivers<a name="EN-US_TOPIC_0000001111039544"></a>
- **[HDF](driver-hdf.md)**
- **[Platform Drivers](driver-platform.md)**
- **[Platform Driver Development](driver-develop.md)**
- **[Peripherals](driver-peripherals.md)**
- **[Platform Driver Usage](driver-platform.md)**
- **[Peripheral Driver Usage](driver-peripherals.md)**
......@@ -49,6 +49,7 @@ The download steps for other resources are the same as those in the mainline ver
- [Platform Driver Porting](porting-smallchip-driver-plat.md)
- [Device Driver Porting](porting-smallchip-driver-oom.md)
- [Standard System Porting Guide](standard-system-porting-guide.md)
- [A Method for Rapidly Porting the OpenHarmony Linux Kernel](porting-linux-kernel-overview.md)
# Third-Party Library Porting Guide
......
# A Method for Rapidly Porting the OpenHarmony Linux Kernel<a name="EN-US_TOPIC_0000001162545194"></a>
- [Overview](#section28051350151118)
- [Overall Porting Approach](#section994883124)
- [Kernel Mode Layer and User Mode Layer](#section953481431217)
- [Composition of the Kernel Mode Layer](#section81437528121)
- [Overall Porting Process](#section86060191)
- [Procedure](#section98871341171310)
- [Setting Up the Environment](#section16584650181314)
- [Porting Basic Kernel-Mode Code](#section95112081716)
- [Porting the HDF Feature](#section12971205681710)
- [Building the Image](#section1681965561911)
- [\(Optional\) Building and Running HDF Test Cases](#section460792312204)
## Overview<a name="section28051350151118"></a>
This document describes how to quickly port OpenHarmony to a third-party chip platform by using the existing capabilities of the Linux kernel of the third-party chip platform.
## Overall Porting Approach<a name="section994883124"></a>
### Kernel Mode Layer and User Mode Layer<a name="section953481431217"></a>
For easy description, we divide the OpenHarmony architecture into two parts:
OpenHarmony = Kernel mode layer + User mode layer
![](figure/technical-architecture.png)
The kernel mode layer is the OpenHarmony kernel layer \(purple part in the figure\). It consists of the kernel, such as Linux Kernel and LiteOS, and features, such as Hardware Driver Foundation \(HDF\), running in the kernel mode.
The user mode layer includes other parts except the OpenHarmony kernel layer. It consists of the system service layer, framework layer, and application layer from the bottom to the top.
The user mode layer of OpenHarmony is loosely coupled with the third-party chip platform and is easy to port. The kernel and HDF at the kernel mode layer are closely coupled with the third-party chip platform and are difficult to port. This document focus on the porting of the kernel mode layer. In addition, it describes only the quick porting of the Linux kernel. It does not include the porting of LiteOS.
### Composition of the Kernel Mode Layer<a name="section81437528121"></a>
The OpenHarmony kernel mode layer can be further divided as follows:
OpenHarmony kernel mode layer = OpenHarmony Linux kernel + OpenHarmony kernel-mode features \(mandatory features, such as HDF, and optional features, such as HMDFS\)
OpenHarmony Linux kernel = Standard LTS Linux kernel + Third-party SoC platform code + OpenHarmony basic kernel-mode code \(most basic code required for running of the OpenHarmony user mode layer\)
Therefore, the OpenHarmony kernel mode layer includes the following:
- Standard LTS Linux kernel
- Third-party SoC platform code
- OpenHarmony basic kernel-mode code
- OpenHarmony kernel-mode features, such as HDF
![](figure/openharmony_kernel.png)
The standard LTS Linux kernel and third-party SoC chip platform code constitute the basis of a third-party Linux kernel. The OpenHarmony kernel mode layer can be composed of either of the following:
- OpenHarmony kernel mode layer = Third-party Linux kernel + OpenHarmony basic kernel-mode code + OpenHarmony kernel-mode features \(such as HDF and HMDFS\)
In this case, the OpenHarmony kernel mode layer consists of the third-party Linux kernel and OpenHarmony basic code and features for the kernel mode.
- OpenHarmony kernel mode layer = OpenHarmony Linux kernel + OpenHarmony kernel-mode features \(such as HDF and HMDFS\)
In this case, the OpenHarmony kernel mode layer consists of OpenHarmony kernel and features. However, the OpenHarmony kernel supports few third-party chip platforms.
In the following, we elaborate how to port OpenHarmony that uses with the third-party Linux kernel.
### Overall Porting Process<a name="section86060191"></a>
The porting process is as follows:
1. Prepare the build environment, including copying the existing kernel code of the third-party chip platform to the OpenHarmony build environment.
2. Port the OpenHarmony basic kernel-mode code.
3. Port OpenHarmony mandatory kernel-mode features \(such as HDF\).
## Procedure<a name="section98871341171310"></a>
The following uses Raspberry Pi 3b \(BCM2837\) as an example to describe how to port OpenHarmony to Raspberry Pi.
### Setting Up the Environment<a name="section16584650181314"></a>
1. Copy the third-party kernel code to the OpenHarmony build environment.
Build the standard Hi3516D V300 kernel, clone the Raspberry Pi kernel source code, and copy it to the manifest output directory.
```
export PROJ_ROOT=[OpenHarmony manifest]
git clone https://gitee.com/xfan1024/oh-rpi3b-kernel.git
cp -r oh-rpi3b-kernel $PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b
```
2. Configure the Raspberry Pi kernel build environment.
```
# Go to the Raspberry Pi kernel directory.
cd out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b
# Configure the build environment, and use clang provided by the project to build the Raspberry Pi kernel source code.
export PATH=$PROJ_ROOT/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PROJ_ROOT/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/:$PATH
export MAKE_OPTIONS="ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CC=clang HOSTCC=clang"
export PRODUCT_PATH=vendor/hisilicon/Hi3516DV300
```
3. Comment out the flags that cannot be recognized by **clang**.
In the **PROJ\_ROOT/out/KERNEL\_OBJ/kernel/src\_tmp/linux-rpi3b/arch/arm/Makefile** file, comment out the following line:
```
KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog
```
### Porting Basic Kernel-Mode Code<a name="section95112081716"></a>
Currently, the basic kernel-mode code of OpenHarmony is related to the log service. The lightweight kernel log service code includes the following:
```
drivers/staging/hilog
drivers/staging/hievent
```
Copy the preceding code from the **kernel/linux/linux-4.19/drivers/staging** directory of OpenHarmony to **out/KERNEL\_OBJ/kernel/src\_tmp/linux-rpi3b/drivers/staging**.
Add the following code to the third-party kernel file **Kconfig** in the **drivers/staging** directory:
```
source "drivers/staging/hilog/Kconfig"
source "drivers/staging/hievent/Kconfig"
```
Enable the CONFIG macros **CONFIG\_HILOG** and **CONFIG\_HIEVENT** in the kernel **config** section.
For details about how to use the logs, see [Hilog\_lite](https://gitee.com/openharmony/hiviewdfx_hilog_lite/blob/master/README.md).
### Porting the HDF Feature<a name="section12971205681710"></a>
1. Install HDF patches.
Run the shell script to apply HDF patches.
1. Set the three variables in the **patch\_hdf.sh** script.
2. Obtain the **patch\_hdf.sh** script.
3. Run the **patch\_hdf.sh** script to pass the three variables in sequence.
Run the following command:
```
./patch_hdf.sh [Project root directory path] [Kernel directory path] [HDF patch file]
```
The following uses Raspberry Pi 3b as an example:
```
# Go to the Raspberry Pi kernel directory.
PROJ_ROOT/drivers/adapter/khdf/linux/patch_hdf.sh \
PROJ_ROOT # Specify the path of the project root directory.\
PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b # Specify the kernel directory for applying the patch.\
PROJ_ROOT/kernel/linux/patches/linux-4.19/hi3516dv300_patch/hdf.patch # HDF patch file.
```
2. Configure the **config** file.
Configure basic HDF settings. If other functions are required, enable the corresponding driver switch by using **menuconfig**.
After HDF patches are installed, the HDF function is disabled by default. To enable the HDF function, perform the following settings:
```
CONFIG_DRIVERS_HDF=y
CONFIG_HDF_SUPPORT_LEVEL=2
CONFIG_DRIVERS_HDF_PLATFORM=y
CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI=y
CONFIG_DRIVERS_HDF_PLATFORM_GPIO=y
CONFIG_DRIVERS_HDF_PLATFORM_I2C=y
CONFIG_DRIVERS_HDF_PLATFORM_UART=y
CONFIG_DRIVERS_HDF_TEST=y
```
Alternatively, run the following command to enable the HDF configuration on the **menuconfig** page:
```
# Generate the .config file.
make ${MAKE_OPTIONS} rpi3b_oh_defconfig
# Modify the HDF kernel configuration.
make ${MAKE_OPTIONS} menuconfig
# [*] Device Drivers
# [*] HDF driver framework support --->
```
The configuration \(in **Device Drivers** \> **HDF driver framework support**\) is as follows:
![](figure/menuconfig.png)
### Building the Image<a name="section1681965561911"></a>
```
# Run the following command:
make ${MAKE_OPTIONS} -j33 zImage
```
### \(Optional\) Building and Running HDF Test Cases<a name="section460792312204"></a>
**Overview**
The HDF test cases are used to verify basic functions of the HDF framework and peripherals. This document describes the HDF kernel-mode test cases.
**Prerequisites**
- In **menuconfig**, **CONFIG\_DRIVERS\_HDF\_TEST** is set to **y**.
- The standard Hi3516D V300 kernel is built completely.
**Test Case Build and Test Method**
Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/oem_subsys_toolchain_hdc_guide.md) tool to push the test case execution file to the device and execute the test cases. The procedure is as follows:
1. Build the HDF test cases.
2. Use the **hdc\_std** tool to push the test case execution file to the device.
3. Go to the **data/test** directory of the device and execute the test file.
The procedure is as follows:
1. Build the HDF test cases.
Run the following command:
```
./build.sh --product-name Hi3516DV300 --build-target hdf_test
```
Wait until the build is complete.
2. Copy the test files to the target device \(Raspberry Pi in this example\).
Method 1: Use the [hdc\_std](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/oem_subsys_toolchain_hdc_guide.md) tool.
1. Create the **data/test** directory in Raspberry Pi.
```
mkdir -p data/test
```
2. Push the dependencies and test cases to Raspberry Pi.
```
hdc file send XXX\out\ohos-arm-release\hdf\hdf\libhdf_test_common.z.so /system/lib
hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test
hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\devmgr\DevMgrTest /data/test
hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\osal\OsalTest /data/test
hdc file send XXX\out\ohos-arm-release\tests\unittest\hdf\sbuf\SbufTest /data/test
```
Method 2: Copy the test files to Raspberry Pi using its memory card.
1. Remove the serial port and USB cable of Raspberry Pi from the PC, and remove its memory card. The **zImage** file in the memory card will be replaced. Back it up in advance.
2. Insert the memory card into the port of the PC used for porting, download the **zImage** file and the **test/** folder to the PC, and then copy them to the root directory of the memory card.
3. Insert the memory card into Raspberry Pi.
```
# Enable the Raspberry Pi file system to read the root directory of the memory card.
mount -t vfat /dev/block/mmcblk0p1 /boot
cd /boot/[Test file directory]
# Enable system files to be modified.
mount -o remount,rw /
# Install the test library.
mv libhdf_test_common.z.so /system/lib
mkdir /data/test
mv * /data/test
```
3. Perform the test.
1. Go to the **data/test** directory.
```
cd /data/test
```
2. Assign the execute permission on the test files.
```
chmod 777 hdf_adapter_uhdf_test_config DevMgrTest OsalTest SbufTest
```
3. Start the test.
```
./hdf_adapter_uhdf_test_config
./DevMgrTest
./OsalTest
./SbufTest
```
4. If **PASSED** is displayed for all test items, HDF is functioning.
Example: DevMgrTest case
```
./DevMgrTest
Running main() from gmock_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from DevMgrTest
[ RUN ] DevMgrTest.DriverLoaderTest_001
[ OK ] DevMgrTest.DriverLoaderTest_001 (0 ms)
[----------] 1 test from DevMgrTest (0 ms total)
[----------] Global test environment tear-down
Gtest xml output finished
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 1 test.
```
......@@ -8,7 +8,7 @@
Hi3516D V300 is a next-generation system on chip \(SoC\) designed for the industry-dedicated smart HD IP camera. It introduces a next-generation image signal processor \(ISP\), the H.265 video compression encoder, and a high-performance NNIE engine, leading the industry in terms of low bit rate, high image quality, intelligent processing and analysis, and low power consumption.
**Figure 1** Hi3516D V300 front view<a name="fig6340825506"></a>
![](figure/hi3516d-v300-front-view.png "hi3516d-v300-front-view")
![](figures/hi3516d-v300-front-view.png "hi3516d-v300-front-view")
## Development Board Specifications<a name="section15192203316533"></a>
......
......@@ -8,10 +8,10 @@
Hi3518E V300 is a next-generation system on chip \(SoC\) designed for the industry-dedicated smart HD IP camera. It introduces a next-generation image signal processor \(ISP\), the H.265 video compression encoder, and the advanced low-power process and architecture design, leading the industry in terms of low bit rate, high image quality, and low power consumption.
**Figure 1** Hi3518E V300 front view<a name="fig73059502010"></a>
![](figure/hi3518e-v300-front-view.png "hi3518e-v300-front-view")
![](figures/hi3518e-v300-front-view.png "hi3518e-v300-front-view")
**Figure 2** Hi3518E V300 rear view<a name="fig14828141713116"></a>
![](figure/hi3518e-v300-rear-view.png "hi3518e-v300-rear-view")
![](figures/hi3518e-v300-rear-view.png "hi3518e-v300-rear-view")
## Development Board Specifications<a name="section765112478446"></a>
......
......@@ -10,12 +10,12 @@
The Hi3861 WLAN module is a development board with 2 x 5 cm form factor. It contains a 2.4 GHz WLAN SoC that highly integrates the IEEE 802.11b/g/n baseband and radio frequency \(RF\) circuit. This module provides open and easy-to-use development and debugging environments for running OpenHarmony.
**Figure 1** Appearance of Hi3861 WLAN module<a name="fig5781557185810"></a>
![](figure/appearance-of-hi3861-wlan-module.png "appearance-of-hi3861-wlan-module")
![](figures/appearance-of-hi3861-wlan-module.png "appearance-of-hi3861-wlan-module")
The Hi3861 WLAN module can also be connected to the Hi3861 mother board to expand its peripheral capabilities. The following figure shows the Hi3861 mother board.
**Figure 2** Appearance of the Hi3861 mother board<a name="fig12182375916"></a>
![](figure/appearance-of-the-hi3861-mother-board.png "appearance-of-the-hi3861-mother-board")
![](figures/appearance-of-the-hi3861-mother-board.png "appearance-of-the-hi3861-mother-board")
- The RF circuit includes modules such as the power amplifier \(PA\), low noise amplifier \(LNA\), RF Balun, antenna switch, and power management. It supports a standard bandwidth of 20 MHz and a narrow bandwidth of 5 MHz or 10 MHz, and provides a maximum rate of 72.2 Mbit/s at the physical layer.
- The Hi3861 WLAN baseband supports the orthogonal frequency division multiplexing \(OFDM\) technology and is backward compatible with the direct sequence spread spectrum \(DSSS\) and complementary code keying \(CCK\) technologies. In addition, the Hi3861 WLAN baseband supports various data rates specified in the IEEE 802.11 b/g/n protocol.
......@@ -23,7 +23,7 @@ The Hi3861 WLAN module can also be connected to the Hi3861 mother board to expan
- The Hi3861 chip applies to Internet of Things \(IoT\) devices such as smart home appliances.
**Figure 3** Hi3861 functions<a name="fig1367035113590"></a>
![](figure/hi3861-functions.png "hi3861-functions")
![](figures/hi3861-functions.png "hi3861-functions")
## Resources and Constraints<a name="section82610215014"></a>
......
......@@ -92,7 +92,7 @@ You need to acquire [source code](../get-code/sourcecode-acquire.md), download
Run the following command to install the libraries and tools required for compilation:
```
sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi
sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi cpio device-tree-compiler
```
## Installing Python3<a name="section1238412211211"></a>
......@@ -112,7 +112,7 @@ sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg
cat /etc/issue
```
1. Install Python based on the Ubuntu version.
2. Install Python based on the Ubuntu version.
- If the Ubuntu version is 18 or later, run the following command:
```
......@@ -175,7 +175,7 @@ sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg
3. Decompress the LLVM installation package to **\~/llvm**.
```
tar -zxvf llvm.tar.gz -C ~/
tar -zxvf llvm.tar -C ~/
```
4. Set an environment variable.
......
# Setting Up Windows Development Environment<a name="EN-US_TOPIC_0000001196067299"></a>
# Setting Up Windows Development Environment<a name="EN-US_TOPIC_0000001216018805"></a>
- [Obtaining the Software](#en-us_topic_0000001058091994_section1483143015558)
- [Installing Visual Studio Code](#en-us_topic_0000001058091994_section71401018163318)
- [Installing Python](#en-us_topic_0000001058091994_section16266553175320)
- [Installing Node.js](#en-us_topic_0000001058091994_section5353233124511)
- [Installing HPM](#en-us_topic_0000001058091994_section173054793610)
- [Installing the DevEco Device Tool Plug-in](#en-us_topic_0000001058091994_section4336315185716)
- [Installing DevEco Device Tool](#en-us_topic_0000001058091994_section10761564496)
System requirements:
- OS: 64-bit Windows 10
- User name: cannot contain Chinese characters
DevEco Device Tool is a plug-in for Visual Studio Code. The installation procedure includes five parts:
1. Installing Visual Studio Code
2. Installing Python
3. Installing Node.js
4. Installing HPM
5. Installing the DevEco Device Tool Plug-in
## Obtaining the Software<a name="en-us_topic_0000001058091994_section1483143015558"></a>
<a name="en-us_topic_0000001058091994_table12730195765616"></a>
<table><thead align="left"><tr id="en-us_topic_0000001058091994_row6730125785610"><th class="cellrowborder" valign="top" width="19.49%" id="mcps1.1.5.1.1"><p id="en-us_topic_0000001058091994_p1573065716561"><a name="en-us_topic_0000001058091994_p1573065716561"></a><a name="en-us_topic_0000001058091994_p1573065716561"></a>Tool</p>
</th>
<th class="cellrowborder" valign="top" width="20.5%" id="mcps1.1.5.1.2"><p id="en-us_topic_0000001058091994_p197306572566"><a name="en-us_topic_0000001058091994_p197306572566"></a><a name="en-us_topic_0000001058091994_p197306572566"></a>Description</p>
</th>
<th class="cellrowborder" valign="top" width="20.03%" id="mcps1.1.5.1.3"><p id="en-us_topic_0000001058091994_p373085711569"><a name="en-us_topic_0000001058091994_p373085711569"></a><a name="en-us_topic_0000001058091994_p373085711569"></a>Version</p>
</th>
<th class="cellrowborder" valign="top" width="39.98%" id="mcps1.1.5.1.4"><p id="en-us_topic_0000001058091994_p197309576566"><a name="en-us_topic_0000001058091994_p197309576566"></a><a name="en-us_topic_0000001058091994_p197309576566"></a>How to Obtain</p>
</th>
</tr>
</thead>
<tbody><tr id="en-us_topic_0000001058091994_row12730155765618"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p123931728135713"><a name="en-us_topic_0000001058091994_p123931728135713"></a><a name="en-us_topic_0000001058091994_p123931728135713"></a>Visual Studio Code</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p12332194816317"><a name="en-us_topic_0000001058091994_p12332194816317"></a><a name="en-us_topic_0000001058091994_p12332194816317"></a>Code editing tool</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p711918919618"><a name="en-us_topic_0000001058091994_p711918919618"></a><a name="en-us_topic_0000001058091994_p711918919618"></a>V1.53 or later (64-bit)</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p2721438193710"><a name="en-us_topic_0000001058091994_p2721438193710"></a><a name="en-us_topic_0000001058091994_p2721438193710"></a><a href="https://code.visualstudio.com/Download" target="_blank" rel="noopener noreferrer">https://code.visualstudio.com/Download</a></p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row187311257185619"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p21270444579"><a name="en-us_topic_0000001058091994_p21270444579"></a><a name="en-us_topic_0000001058091994_p21270444579"></a>Python</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p547205817316"><a name="en-us_topic_0000001058091994_p547205817316"></a><a name="en-us_topic_0000001058091994_p547205817316"></a>Programming tool</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p1991315166416"><a name="en-us_topic_0000001058091994_p1991315166416"></a><a name="en-us_topic_0000001058091994_p1991315166416"></a>V3.8.9 or later (64-bit)</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p108321457411"><a name="en-us_topic_0000001058091994_p108321457411"></a><a name="en-us_topic_0000001058091994_p108321457411"></a><a href="https://www.python.org/downloads/" target="_blank" rel="noopener noreferrer">https://www.python.org/downloads/</a></p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row117316576562"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p16405151165717"><a name="en-us_topic_0000001058091994_p16405151165717"></a><a name="en-us_topic_0000001058091994_p16405151165717"></a>Node.js</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p1773185765616"><a name="en-us_topic_0000001058091994_p1773185765616"></a><a name="en-us_topic_0000001058091994_p1773185765616"></a>The npm environment provider</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p16304104120181"><a name="en-us_topic_0000001058091994_p16304104120181"></a><a name="en-us_topic_0000001058091994_p16304104120181"></a>Any of the following versions:</p>
<a name="en-us_topic_0000001058091994_ul875854471719"></a><a name="en-us_topic_0000001058091994_ul875854471719"></a><ul id="en-us_topic_0000001058091994_ul875854471719"><li>V12.22.5 or later (64-bit)</li><li>V14.17.5 or later (64-bit)</li><li>V16.6.0 or later (64-bit)</li></ul>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p9200911141112"><a name="en-us_topic_0000001058091994_p9200911141112"></a><a name="en-us_topic_0000001058091994_p9200911141112"></a><a href="https://nodejs.org/en/download/" target="_blank" rel="noopener noreferrer">https://nodejs.org/en/download/</a></p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row6731105715561"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p2081865318571"><a name="en-us_topic_0000001058091994_p2081865318571"></a><a name="en-us_topic_0000001058091994_p2081865318571"></a>HPM</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p1632215161040"><a name="en-us_topic_0000001058091994_p1632215161040"></a><a name="en-us_topic_0000001058091994_p1632215161040"></a>Package manager</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p773185715566"><a name="en-us_topic_0000001058091994_p773185715566"></a><a name="en-us_topic_0000001058091994_p773185715566"></a>V1.3.0 or later</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p14731125745610"><a name="en-us_topic_0000001058091994_p14731125745610"></a><a name="en-us_topic_0000001058091994_p14731125745610"></a>For details, see <a href="#en-us_topic_0000001058091994_section173054793610">Installing HPM</a>.</p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row13317205645717"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p143411112587"><a name="en-us_topic_0000001058091994_p143411112587"></a><a name="en-us_topic_0000001058091994_p143411112587"></a>DevEco Device Tool</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p1690316506517"><a name="en-us_topic_0000001058091994_p1690316506517"></a><a name="en-us_topic_0000001058091994_p1690316506517"></a>Plug-in for the OpenHarmony source code compilation, programming, and debugging</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p113171956185715"><a name="en-us_topic_0000001058091994_p113171956185715"></a><a name="en-us_topic_0000001058091994_p113171956185715"></a>V2.2 Beta2</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p3503163074720"><a name="en-us_topic_0000001058091994_p3503163074720"></a><a name="en-us_topic_0000001058091994_p3503163074720"></a><a href="https://device.harmonyos.com/cn/ide#download_beta" target="_blank" rel="noopener noreferrer">https://device.harmonyos.com/cn/ide#download_beta</a></p>
<p id="en-us_topic_0000001058091994_p23171856135717"><a name="en-us_topic_0000001058091994_p23171856135717"></a><a name="en-us_topic_0000001058091994_p23171856135717"></a>Log in with your HUAWEI ID to download it. You can <a href="https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148" target="_blank" rel="noopener noreferrer">register an account here</a>.</p>
</td>
</tr>
</tbody>
</table>
## Installing Visual Studio Code<a name="en-us_topic_0000001058091994_section71401018163318"></a>
## Installing DevEco Device Tool<a name="en-us_topic_0000001058091994_section10761564496"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you have installed Visual Studio Code, open the CLT and run **code --version** to check whether the version is 1.53 or later. If the version number is returned, it indicates that the environment variables are set correctly.
1. Double-click the Visual Studio Code package to install it. During the installation, select **Add to PATH \(requires shell restart\)**.
![](figure/installing-visual-studio-code.png)
2. After the installation is complete, open the CLT and run **code --version**. If the version number can be displayed, it indicates that the installation is successful.
## Installing Python<a name="en-us_topic_0000001058091994_section16266553175320"></a>
1. Double-click the Python software package, select **Add Python 3.8 to PATH**, and click **Install Now**.
![](figure/installing-python.png)
2. After the installation is complete, click **Close**.
DevEco Device Tool is installed in Visual Studio Code as a plug-in and depends on Python, Node.js, and HPM for running.
![](figure/setup-was-successful.png)
3. Open the CLT, and run **python --version** to check the installation result.
![](figure/checking-the-installation-result.png)
4. In the CLT, run the following commands to set the pip source for downloading the dependencies required for later installation:
```
pip config set global.trusted-host repo.huaweicloud.com
pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple
pip config set global.timeout 120
```
## Installing Node.js<a name="en-us_topic_0000001058091994_section5353233124511"></a>
DevEco Device Tool supports integrated installation. The DevEco Device Tool setup wizard checks whether the adaptation versions of Visual Studio Code, Python, Node.js and HPM tools have been installed. If any of the tools is not installed, you'll be prompted to select the tool to be automatically installed.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you have installed Node.js, open the CLT and run **node -v** to check whether the version is 12.0.0 or later.
1. Run the downloaded software package to install. Use the default settings when following the installation wizard, and click **Next** until **Finish** is displayed. During the installation, Node.js will automatically set the system Path environment variable to the installation directory of **node.exe**.
2. Open the CLT and run **node -v**. If the version number of Node.js is displayed, it indicates that Node.js has been successfully installed.
>Before installing DevEco Device Tool, make sure the user name of the host does not contain Chinese characters. Otherwise, the **DevEco Home** page will be stuck loading and the DevEco Device Tool cannot work.
## Installing HPM<a name="en-us_topic_0000001058091994_section173054793610"></a>
1. Log in to the [HarmonyOS Device website](https://device.harmonyos.com/cn/ide#download_beta) with your HUAWEI ID and download DevEco Device Tool V3.0 Beta1 or a later version. If you do not have a HUAWEI ID, [register](https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148) one first.
2. Decompress the DevEco Device Tool package, double-click the installer, and then click **Next**.
3. Set the installation path of DevEco Device Tool and click **Next**.
4. When prompted, select the tools to be automatically installed and click **Next**.
Before installing HPM, ensure that Node.js has been installed
![](figures/snap28.png)
and that your network can access the Internet. If your network requires a proxy to access the Internet, [set up the npm proxy](https://device.harmonyos.com/en/docs/ide/user-guides/npm_proxy-0000001054491032) first.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If HPM has been installed, run **npm update -g @ohos/hpm-cli** to update it to the latest version.
1. You are advised to set the npm source to an image in China, for example, a HUAWEI CLOUD image source.
```
npm config set registry https://repo.huaweicloud.com/repository/npm/
```
2. Open the CLT and run the following command to install the latest version of HPM:
```
npm install -g @ohos/hpm-cli
```
![](figure/hpm-version.png)
3. After the installation is complete, run the following command to obtain the installation result:
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>When the setup wizard detects that a compatible Python version has been installed, it prompts you to select the installed Python version or download the recommended Python version.
```
hpm -V
```
5. In the dialog box shown below, click **Next** to download and install the tools.
![](figures/snap8.png)
## Installing the DevEco Device Tool Plug-in<a name="en-us_topic_0000001058091994_section4336315185716"></a>
6. In the displayed Python setup wizard, select **Add Python 3.8 to PATH** and click **Install Now**. After the installation is complete, click **Close**.
Before installing DevEco Device Tool, make sure the user name of the host does not contain Chinese characters. Otherwise, the **DevEco Home** page will be stuck loading and the DevEco Device Tool cannot work.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you have selected the compatible Python version installed on your device, the Python setup wizard will not be displayed. In this case, you skip this step.
>If DevEco Device Tool 2.1 Release is installed, the Python version must be 3.8.x. If DevEco Device Tool V3.0 Beta1 or a later version is installed, the Python version must be 3.8.x or 3.9.x.
DevEco Device Tool will automatically download and install the C/C++ and CodeLLDB plug-ins from the Visual Studio Code Marketplace during the installation process. Therefore, make sure Visual Studio Code can access the Internet. If your network requires a proxy to access the Internet, [set up the Visual Studio Code proxy](https://device.harmonyos.com/en/docs/ide/user-guides/vscode_proxy-0000001074231144) first.
![](figures/snap34.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Before installing DevEco Device Tool, ensure that Visual Studio Code is closed.
1. Decompress the DevEco Device Tool plug-in package and double-click the installer to install.
2. DevEco Device Tool checks whether the toolkit on which the installation depends meets the requirements. If the requirements are not met, follow the preceding installation instructions in this section.
7. In the Visual Studio Code setup wizard, install Visual Studio Code as prompted. During the installation, select **Add to PATH \(requires shell restart\)**.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If Visual Studio Code has been installed but fails to be detected, restart your computer.
>If you are using the correct version of Visual Studio Code, the Visual Studio Code setup wizard will not be displayed. In this case, you skip this step.
![](figure/installing-the-deveco-device-tool.png)
![](figures/snap33.png)
3. Click **Install**.
8. In the Node.js setup wizard, retain the default settings and click **Next** until **Finish** is displayed. During the installation, Node.js will automatically set the system Path environment variable to the installation directory of **node.exe**.
![](figure/install.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you are using the correct version of Node.js, the Node.js setup wizard will not be displayed. In this case, you skip this step.
4. After the installation is complete, click **Close**.
9. Wait for the DevEco Device Tool setup wizard to automatically install the HPM and DevEco Device Tool. After the installation is complete, click **Finish** to close the setup wizard.
![](figure/installation-complete.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you are using the correct version of HPM, the setup wizard does not download or install HPM.
5. Start Visual Studio Code. The C/C++ and CodeLLDB plug-ins on which DevEco Device Tool depends will be automatically installed. After the installation is complete, click![](figure/button.png)on the left of Visual Studio Code to check whether C/C++, CodeLLDB, and DevEco Device Tool are included in the INSTALLED list.
10. Start Visual Studio Code. The C/C++ and CodeLLDB plug-ins on which DevEco Device Tool depends will be automatically installed. After the installation is complete, click ![](figures/button.png) on the left of Visual Studio Code to check whether C/C++, CodeLLDB, and DevEco Device Tool are included in the **INSTALLED** list.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the C/C++ and CodeLLDB plug-ins fail to be installed, DevEco Device Tool cannot run properly. To solve the issue, see [Installing the C/C++ and CodeLLDB Plug-ins Offline](https://device.harmonyos.com/en/docs/ide/user-guides/offline_plugin_install-0000001074376846).
![](figure/visual-studio-code.png)
![](figures/deveco-device-tool-install-sucessful.png)
# FAQs<a name="EN-US_TOPIC_0000001128470856"></a>
- [What should I do when the images failed to be burnt over the selected serial port?](#section627268185113)
- ["Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning](#section627268185113)
- [What should I do when Windows-based PC failed to be connected to the board?](#section195391036568)
- [What should I do when the image failed to be burnt?](#section571164016565)
- [What should I do when the message indicating Python cannot be found is displayed during compilation and building?](#section1039835245619)
- [What should I do when no command output is displayed?](#section14871149155911)
## What should I do when the images failed to be burnt over the selected serial port?<a name="section627268185113"></a>
## "Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning<a name="section627268185113"></a>
- **Symptom**
**Error: Opening COMxx: Access denied** is displayed after clicking **Burn** and selecting a serial port.
**Figure 1** Failed to open the serial port<a name="fig1756105874814"></a>
![](figure/failed-to-open-the-serial-port.png "failed-to-open-the-serial-port")
![](figures/failed-to-open-the-serial-port.png)
- **Possible Causes**
The serial port has been used.
- **Solutions**
1. Search for the terminal using serial-xx from the drop-down list in the **TERMINAL** panel.
**Figure 2** Checking whether the serial port is used<a name="fig723433664916"></a>
![](figure/checking-whether-the-serial-port-is-used.png "checking-whether-the-serial-port-is-used")
- Solution
2. Click the dustbin icon as shown in the following figure to disable the terminal using the serial port.
The serial port may be in use. Perform the following steps to troubleshoot:
**Figure 3** Disabling the terminal using the serial port<a name="fig197211713185012"></a>
![](figure/disabling-the-terminal-using-the-serial-port.png "disabling-the-terminal-using-the-serial-port")
1. Search for the serial port from the drop-down list in the **TERMINAL** panel.
3. Click **Burn**, select the serial port, and start burning images again.
![](figures/terminal-list.png)
**Figure 4** Restarting burning<a name="fig2196042514"></a>
![](figure/restarting-burning.png "restarting-burning")
2. Click the dustbin for the terminal using the serial port to disable the terminal.
## What should I do when Windows-based PC failed to be connected to the board?<a name="section195391036568"></a>
......@@ -43,8 +35,8 @@
The file image cannot be obtained after clicking **Burn** and selecting a serial port.
**Figure 5** Failed to obtain the image file due to unavailable connection<a name="fig135261439195819"></a>
![](figure/failed-to-obtain-the-image-file-due-to-unavailable-connection.png "failed-to-obtain-the-image-file-due-to-unavailable-connection")
**Figure 1** Failed to obtain the image file due to unavailable connection<a name="fig135261439195819"></a>
![](figures/failed-to-obtain-the-image-file-due-to-unavailable-connection.png "failed-to-obtain-the-image-file-due-to-unavailable-connection")
- **Possible Causes**
......@@ -57,23 +49,19 @@
1. Check whether the network cable is properly connected.
2. Click **Windows Firewall**.
**Figure 6** Network and firewall setting<a name="fig168416458311"></a>
![](figure/network-and-firewall-setting.png "network-and-firewall-setting")
![](figures/hi3516-network-and-firewall-setting.png)
3. Click **Firewall & network protection**, and on the displayed page, click **Allow applications to communicate through Windows Firewall**.
**Figure 7** Firewall and network protection<a name="fig19866154513414"></a>
![](figure/firewall-and-network-protection.png "firewall-and-network-protection")
![](figures/hi3516-firewall-and-network-protection.png)
4. Select the Visual Studio Code application.
**Figure 8** Selecting the Visual Studio Code application<a name="fig9213244657"></a>
![](figure/selecting-the-visual-studio-code-application.png "selecting-the-visual-studio-code-application")
![](figures/hi3516-selecting-the-visual-studio-code-application.png)
5. Select the **Private** and **Public** network access rights for the Visual Studio Code application.
**Figure 9** Allowing the Visual Studio Code application to access the network<a name="fig019395421210"></a>
![](figure/allowing-the-visual-studio-code-application-to-access-the-network.png "allowing-the-visual-studio-code-application-to-access-the-network")
![](figures/hi3516-allowing-the-visual-studio-code-application-to-access-the-network.png)
## What should I do when the image failed to be burnt?<a name="section571164016565"></a>
......@@ -95,17 +83,17 @@
- **Symptom**
![](figure/symptom.png)
![](figures/symptom-for-not-finding-python.png)
- **Possible Cause 1**: Python is not installed.
- **Solutions**
Install Python as instructed in [Installing and Configuring Python](quickstart-lite-env-setup-linux.md#section1238412211211).
[Install Python](../quick-start/quickstart-lite-env-setup-linux.md).
- **Possible Cause 2**: The soft link that points to the Python does not exist in the usr/bin directory.
![](figure/reason-for-not-finding-python.png)
![](figures/reason-for-not-finding-python.png)
- **Solutions**
......@@ -120,7 +108,7 @@
Example:
![](figure/solution-7.png)
![](figures/solution.png)
## What should I do when no command output is displayed?<a name="section14871149155911"></a>
......@@ -137,7 +125,7 @@
Change the serial port number.
Start **Device Manager** to check whether the serial port connected to the board is the same as that connected to the terminal device. If the serial ports are different, perform step [1](#section627268185113) in the **Running an Image** section to change the serial port number.
Start **Device Manager** to check whether the serial port connected to the board is the same as that connected to the terminal device. If the serial ports are different, perform step 1 in the **Running an Image** section to change the serial port number.
- **Possible Cause 2**
......@@ -164,7 +152,7 @@
3. Log in to the serial port after the burning is complete.
**Figure 10** Serial port displayed after the U-Boot is burnt<a name="en-us_topic_0000001053466255_fig155914681910"></a>
![](figure/serial-port-displayed-after-the-u-boot-is-burnt.png "serial-port-displayed-after-the-u-boot-is-burnt")
**Figure 2** Serial port displayed after the U-Boot is burnt<a name="en-us_topic_0000001053466255_fig155914681910"></a>
![](figures/serial-port-displayed-after-the-u-boot-is-burnt.png "serial-port-displayed-after-the-u-boot-is-burnt")
......@@ -433,13 +433,13 @@ Perform the [building](quickstart-lite-steps-hi3516-running.md#section107767131
>If the connection fails, rectify the fault by referring to [FAQs](quickstart-lite-steps-hi3516-faqs.md#section14871149155911).
**Figure 1** Serial port connection<a name="fig124315964718"></a>
![](figure/serial-port-connection-5.png "serial-port-connection-5")
![](figures/serial-port-connection.png "serial-port-connection")
1. Click **Monitor** to enable the serial port.
2. Press **Enter** repeatedly until **hisilicon** displays.
3. Go to step [2](quickstart-lite-steps-hi3516-running.md#l5b42e79a33ea4d35982b78a22913b0b1) if the board is started for the first time or the startup parameters need to be modified; go to step [3](quickstart-lite-steps-hi3516-running.md#ld26f18828aa44c36bfa36be150e60e49) otherwise.
3. Go to step [2](#li109940111259) if the board is started for the first time or the startup parameters need to be modified; go to step [3](#li448312542515) otherwise.
2. \(Mandatory when the board is started for the first time\) Modify the **bootcmd** and **bootargs** parameters of U-Boot. You need to perform this step only once if the parameters need not to be modified during the operation. The board automatically starts after it is reset.
2. <a name="li109940111259"></a>\(Mandatory when the board is started for the first time\) Modify the **bootcmd** and **bootargs** parameters of U-Boot. You need to perform this step only once if the parameters need not to be modified during the operation. The board automatically starts after it is reset.
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>The default waiting time in the U-Boot is 2s. You can press **Enter** to interrupt the waiting and run the **reset** command to restart the system after "hisilicon" is displayed.
......@@ -480,10 +480,10 @@ Perform the [building](quickstart-lite-steps-hi3516-running.md#section107767131
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>**go 0x80000000** is optional. It indicates that the command is fixed in the startup parameters by default and the board automatically starts after it is reset. If you want to manually start the board, press **Enter** in the countdown phase of the U-Boot startup to interrupt the automatic startup.
3. Run the **reset** command and press **Enter** to restart the board. After the board is restarted, **OHOS** is displayed when you press **Enter**.
3. <a name="li448312542515"></a>Run the **reset** command and press **Enter** to restart the board. After the board is restarted, **OHOS** is displayed when you press **Enter**.
**Figure 2** System startup<a name="fig14618415485"></a>
![](figure/system-startup-6.png "system-startup-6")
![](figures/system-startup.png "system-startup")
4. In the root directory, run the **./bin/hello\_uart** command line to execute the demo program. The compilation result is shown in the following example.
......
......@@ -3,9 +3,9 @@
- [Creating a Program](#section204672145202)
- [Building](#section1077671315253)
- [Burning](#section1347011412201)
- [Programming Flash Memory Through the Network Port](#section1935410617363)
- [Burning Through the Network Port](#section1935410617363)
- [Running an Image](#section24721014162010)
- [Running an Image](#section24721014162010)
- [Running a Program](#section5276734182615)
This section describes how to create, compile, burn, and run the first program, and finally print **Hello OHOS!** on the develop board.
......@@ -140,8 +140,8 @@ Select ipcamera_hispark_taurus@hisilicon and press Enter.
hb build -f (Start building.)
```
**Figure 1** Settings<a name="fig1458988766"></a>
![](figure/settings.png "settings")
**Figure 1** Hi3516 settings<a name="fig1458988766"></a>
![](figures/hi3516-settings.png "hi3516-settings")
The result files are generated in the **out/hispark\_taurus/ipcamera\_hispark\_taurus** directory.
......@@ -152,9 +152,9 @@ The result files are generated in the **out/hispark\_taurus/ipcamera\_hispark\_
The Hi3516 development board allows you to burn flash memory over the USB port, serial port, or network port. The following uses the network port burning as an example.
### Programming Flash Memory Through the Network Port<a name="section1935410617363"></a>
### Burning Through the Network Port<a name="section1935410617363"></a>
To program flash memory through the network port in the Windows or Linux environment:
To burn Hi3516D V300 through the network port in the Windows or Linux environment:
1. Connect the PC and the target development board through the serial port, network port, and power port. For details, see [Introduction to the Hi3516 Development Board](https://device.harmonyos.com/en/docs/start/introduce/oem_minitinier_des_3516-0000001152041033).
2. <a name="en-us_topic_0000001056443961_li142386399535"></a>Open Device Manager, then check and record the serial port number corresponding to the development board.
......@@ -162,73 +162,74 @@ To program flash memory through the network port in the Windows or Linux environ
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the serial port number is not displayed correctly, follow the steps described in [Installing the Serial Port Driver on the Hi3516 or Hi3518 Series Development Boards](https://device.harmonyos.com/en/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695).
![](figure/record-the-serial-port-number-1.png)
![](figures/hi3516-record-the-serial-port-number.png)
3. Open DevEco Device Tool and go to **Projects** \> **Settings**.
3. Open DevEco Device Tool, choose **QUICK ACCESS** \> **DevEco Home** \> **Projects**, and then click **Settings**.
![](figure/settings-2.png)
![](figures/hi3516-deveco-device-tool-setting.png)
4. On the **Partition Configuration** tab page, modify the settings. In general cases, you can leave the fields at their default settings.
5. On the **hi3516dv300** tab page, configure the programming options.
5. On the **hi3516dv300** tab page, configure the burning options.
- **upload\_port**: Select the serial port number obtained in step [2](#en-us_topic_0000001056443961_li142386399535).
- **upload\_protocol**: Select the programming protocol **hiburn-net**.
- **upload\_partitions**: Select the file to be programmed. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are programmed at the same time.
- **upload\_protocol**: Select the burning protocol **hiburn-net**.
- **upload\_partitions**: Select the file to be burnt. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are burnt at the same time.
![](figure/hi3516-upload-options.png)
![](figures/hi3516-upload-options.png)
6. <a name="en-us_topic_0000001056443961_li1558813168234"></a>Check and set the IP address of the network adapter connected to the development board. For details, see [Setting the IP Address of the Network Port for Programming on Hi3516](https://device.harmonyos.com/en/docs/ide/user-guides/set_ipaddress-0000001141825075).
7. Set the IP address of the network port for programming:
6. <a name="en-us_topic_0000001056443961_li1558813168234"></a>Check and set the IP address of the network adapter connected to the development board. For details, see [Setting the IP Address of the Network Port for Burning to Hi3516](https://device.harmonyos.com/en/docs/ide/user-guides/set_ipaddress-0000001141825075).
7. Set the IP address of the network port for burning:
- **upload\_net\_server\_ip**: Select the IP address set in step [6](#en-us_topic_0000001056443961_li1558813168234), such as 192.168.1.2.
- **upload\_net\_client\_mask**: Set the subnet mask of the development board, such as 255.255.255.0. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated.
- **upload\_net\_client\_gw**: Set the gateway of the development board, such as 192.168.1.1. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated.
- **upload\_net\_client\_ip**: Set the IP address of the development board, such as 192.168.1.3. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated.
![](figure/ip-address-information.png)
![](figures/ip-address-information.png)
8. When you finish modifying, click **Save** in the upper right corner.
9. Open the project file and go to ![](figure/deveco-device-tool-logo.png) \> **PROJECT TASKS** \> **hi3516dv300** \> **Upload** to start programming.
9. Open the project file and go to ![](figures/hi3516-deveco-device-tool-logo.png) \> **PROJECT TASKS** \> **hi3516dv300** \> **Upload** to start burning.
![](figure/start-burning.png)
![](figures/hi3516-upload-start-burning.png)
10. When the following message is displayed, power off the development board and then power it on.
![](figure/restart-the-development-board-3.png)
![](figures/hi3516-restart-the-development-board.png)
11. Start programming. If the following message is displayed, it indicates that the programming is successful.
11. If the following message is displayed, it indicates that the burning is successful.
![](figure/burning-succeeded-4.png)
![](figures/hi3516-burning-succeeded-net.png)
12. When the burning is successful, perform the operations in Running an Image to start the system.
## Running an Image<a name="section24721014162010"></a>
### Running an Image<a name="section24721014162010"></a>
After programming is completed, you need to configure the bootloader to run the OpenHarmony system.
After burning is completed, you need to configure the bootloader to run the OpenHarmony system.
1. In the Hi3516D V300 task, click **Configure bootloader \(Boot OS\)** to configure the bootloader.
> ![](../public_sys-resources/icon-note.gif) **NOTE:**
> The bootloader configuration in DevEco Device Tool has been adapted to Hi3516D V300. Therefore, no manual modification is needed.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The bootloader configuration in DevEco Device Tool has been adapted to Hi3516D V300. Therefore, no manual modification is needed.
![](figure/bootloader.png)
![](figures/bootloader.png)
2. When the message shown below is displayed, restart the development board. If **SUCCESS** is displayed, it indicates that the configuration is successful.
![](figure/reset_success.png)
![](figures/reset_success.png)
3. Click **Monitor** on the taskbar to start the serial port tool.
![](figure/monitor.png)
![](figures/monitor.png)
4. Follow the onscreen instructions until **OHOS \#** is displayed, indicating that the system is started successfully.
![](figure/reboot_success.png)
![](figures/reboot_success.png)
## Running a Program<a name="section5276734182615"></a>
In the root directory, run the **./bin/helloworld** command to operate the demo program. The compilation result is shown in the following example.
**Figure 4** Successful system startup and program execution<a name="fig149821431194515"></a>
![](figure/successful-system-startup-and-program-execution.png "successful-system-startup-and-program-execution")
**Figure 2** Successful system startup and program execution<a name="fig149821431194515"></a>
![](figures/successful-system-startup-and-program-execution.png "successful-system-startup-and-program-execution")
......@@ -19,8 +19,8 @@
The following figure shows the hardware connections.
**Figure 1** Hardware connections<a name="fig38451744110"></a>
![](figure/hardware-connections-0.png "hardware-connections-0")
**Figure 1** Hi3516 hardware connections<a name="fig86246141414"></a>
![](figures/hi3516-hardware-connections.png "hi3516-hardware-connections")
### Software<a name="section965634210501"></a>
......
# FAQs<a name="EN-US_TOPIC_0000001128311064"></a>
- [What should I do when the images failed to be burnt over the selected serial port?](#section1498892119619)
- ["Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning](#section1498892119619)
- [What should I do when Windows-based PC failed to be connected to the board?](#section8512971816)
- [What should I do when the image failed to be burnt?](#section1767804111198)
- [What should I do when the message indicating Python cannot be found is displayed during compilation and building?](#en-us_topic_0000001053466255_section1039835245619)
- [What should I do when no command output is displayed?](#en-us_topic_0000001053466255_section14871149155911)
## What should I do when the images failed to be burnt over the selected serial port?<a name="section1498892119619"></a>
## "Error: Opening COMxx: Access denied" Is Displayed After a Serial Port Is Selected for Burning<a name="section1498892119619"></a>
- **Symptom**
**Error: Opening COMxx: Access denied** is displayed after clicking **Burn** and selecting a serial port.
**Figure 1** Failed to open the serial port<a name="en-us_topic_0000001053466255_fig066333283916"></a>
![](figure/failed-to-open-the-serial-port-17.png "failed-to-open-the-serial-port-17")
![](figures/failed-to-open-the-serial-port.png)
- **Possible Causes**
The serial port has been used.
- **Solutions**
1. Search for the terminal using serial-xx from the drop-down list in the **TERMINAL** panel.
**Figure 2** Checking whether the serial port is used<a name="en-us_topic_0000001053466255_fig165994164420"></a>
![](figure/checking-whether-the-serial-port-is-used-18.png "checking-whether-the-serial-port-is-used-18")
- Solution
2. Click the dustbin icon as shown in the following figure to disable the terminal using the serial port.
The serial port may be in use. Perform the following steps to troubleshoot:
**Figure 3** Disabling the terminal using the serial port<a name="en-us_topic_0000001053466255_fig7911282453"></a>
![](figure/disabling-the-terminal-using-the-serial-port-19.png "disabling-the-terminal-using-the-serial-port-19")
1. Search for the serial port from the drop-down list in the **TERMINAL** panel.
3. Click **Burn**, select the serial port, and start burning images again.
![](figures/terminal-list.png)
**Figure 4** Restarting burning<a name="fig87139519227"></a>
![](figure/restarting-burning-20.png "restarting-burning-20")
2. Click the dustbin for the terminal using the serial port to disable the terminal.
## What should I do when Windows-based PC failed to be connected to the board?<a name="section8512971816"></a>
......@@ -43,8 +35,8 @@
The file image cannot be obtained after clicking **Burn** and selecting a serial port.
**Figure 5** Failed to obtain the image file due to unavailable connection<a name="en-us_topic_0000001053466255_fig5218920223"></a>
![](figure/failed-to-obtain-the-image-file-due-to-unavailable-connection-21.png "failed-to-obtain-the-image-file-due-to-unavailable-connection-21")
**Figure 1** Failed to obtain the image file due to unavailable connection<a name="en-us_topic_0000001053466255_fig5218920223"></a>
![](figures/failed-to-obtain-the-image-file-due-to-unavailable-connection-0.png "failed-to-obtain-the-image-file-due-to-unavailable-connection-0")
- **Possible Causes**
......@@ -57,23 +49,19 @@
1. Check whether the network cable is properly connected.
2. Click **Windows Firewall**.
**Figure 6** Network and firewall setting<a name="fig954464811215"></a>
![](figure/network-and-firewall-setting-22.png "network-and-firewall-setting-22")
![](figures/hi3518-network-and-firewall-setting.png)
3. Click **Firewall & network protection**, and on the displayed page, click **Allow applications to communicate through Windows Firewall**.
**Figure 7** Firewall and network protection<a name="fig158731526101312"></a>
![](figure/firewall-and-network-protection-23.png "firewall-and-network-protection-23")
![](figures/hi3518-firewall-and-network-protection.png)
4. Select the Visual Studio Code application.
**Figure 8** Selecting the Visual Studio Code application<a name="fig96572537139"></a>
![](figure/selecting-the-visual-studio-code-application-24.png "selecting-the-visual-studio-code-application-24")
![](figures/hi3518-selecting-the-visual-studio-code-application.png)
5. Select the **Private** and **Public** network access rights for the Visual Studio Code application.
**Figure 9** Allowing the Visual Studio Code application to access the network<a name="fig18201217161411"></a>
![](figure/allowing-the-visual-studio-code-application-to-access-the-network-25.png "allowing-the-visual-studio-code-application-to-access-the-network-25")
![](figures/hi3518-allowing-the-visual-studio-code-application-to-access-the-network.png)
## What should I do when the image failed to be burnt?<a name="section1767804111198"></a>
......@@ -95,7 +83,7 @@
- **Symptom**
![](figure/error.png)
![](figures/hi3518-error-for-not-finding-python.png)
- **Possible Cause 1**
......@@ -104,11 +92,11 @@
- **Solutions**
Install Python as instructed in [Installing and Configuring Python](quickstart-lite-env-setup-linux.md#section1238412211211).
[Install Python](../quick-start/quickstart-lite-env-setup-linux.md).
- **Possible Cause 2**: The soft link that points to the Python does not exist in the usr/bin directory.
![](figure/error2.png)
![](figures/hi3518-reason-no-python-soft-link.png)
- **Solutions**
......@@ -123,7 +111,7 @@
Example:
![](figure/solution-26.png)
![](figures/hi3518-solution-set-python-soft-link.png)
## What should I do when no command output is displayed?<a name="en-us_topic_0000001053466255_section14871149155911"></a>
......@@ -140,7 +128,7 @@
Change the serial port number.
Start **Device Manager** to check whether the serial port connected to the board is the same as that connected to the terminal device. If the serial ports are different, perform step [1](#section1498892119619) in the **Running an Image** section to change the serial port number.
Start **Device Manager** to check whether the serial port connected to the board is the same as that connected to the terminal device. If the serial ports are different, perform step 1 in the **Running an Image** section to change the serial port number.
- **Possible Cause 2**
......@@ -167,6 +155,6 @@
3. Log in to the serial port after the burning is complete.
![](figure/login-serial-port.png)
![](figures/login-serial-port.png)
......@@ -139,22 +139,22 @@ hb build -f (Start building.)
The result files are generated in the **out/hispark\_aries/ipcamera\_hispark\_aries** directory.
**Figure 1** Settings<a name="fig1766174411418"></a>
![](figure/settings-9.png "settings-9")
**Figure 1** Hi3518 settings<a name="fig12982192583111"></a>
![](figures/hi3518-settings.png "hi3518-settings")
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>The U-Boot file of the Hi3518E V300 development board can be obtained from the following path: device/hisilicon/hispark\_aries/sdk\_liteos/uboot/out/boot/u-boot-hi3518ev300.bin
## Burning<a name="section7609155824819"></a>
Programming the flash memory is the process of downloading compiled program files to a chipset development board to provide a basis for subsequent debugging. With the one-click flash memory programming function of DevEco Device Tool, you can program flash memory on development boards quickly and efficiently.
Burning is the process of downloading compiled program files to a chipset development board to provide a basis for subsequent debugging. With the one-click burning function of DevEco Device Tool, you can burn development boards quickly and efficiently.
The Hi3518E V300 development board allows you to program flash memory through the USB port or serial port.
You can burn the Hi3518E V300 development board through the USB port or serial port.
- **Windows system: Supports programming through the USB port or serial port**
- **Linux system: Supports programming through the serial port \(Linux+Windows dual system: Supports programming through the serial port or USB port\)**
- **Windows system: Supports burning through the USB port or serial port**
- **Linux system: Supports burning through the serial port \(Linux+Windows dual system: Supports burning through the serial port or USB port\)**
Except for environment setup, the operations of programming are the same for Windows and Linux.
Except for environment setup, the operations of burning are the same for Windows and Linux.
The following uses the USB port burning as an example.
......@@ -164,68 +164,76 @@ The following uses the USB port burning as an example.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the serial port number is not displayed correctly, follow the steps described in [Installing the Serial Port Driver on the Hi3516 or Hi3518 Series Development Boards](https://device.harmonyos.com/en/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695).
![](figure/record-the-serial-port-number-10.png)
![](figures/hi3518-record-the-serial-port-number.png)
3. Open DevEco Device Tool and go to **Projects** \> **Settings**.
3. Open DevEco Device Tool, choose **QUICK ACCESS** \> **DevEco Home** \> **Projects**, and then click **Settings**.
![](figure/setting-11.png)
![](figures/hi3518-deveco-device-tool-setting.png)
4. On the **Partition Configuration** tab page, modify the settings. In general cases, you can leave the fields at their default settings.
5. On the **hi3518ev300** tab page, set the programming options.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the file to be burnt is obtained by copying, you must manually change the path of the file to be burnt: Click the tab of the file to be burnt, select **Partition\_bin** from the **New Option** drop-down list box in **Partition Settings**, and set the path of the file to be burnt in **Partition\_bin**.
5. On the **hi3518ev300** tab page, set the burning options.
- **upload\_port**: Select the serial port number obtained in step [2](#en-us_topic_0000001057313128_li46411811196).
- **upload\_protocol**: Select the programming protocol **hiburn-usb**.
- **upload\_partitions**: Select the file to be programmed. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are programmed at the same time.
- **upload\_protocol**: Select the burning protocol **hiburn-usb**.
- **upload\_partitions**: Select the files to be burnt. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are burnt at the same time.
![](figure/upload-options.png)
![](figures/upload-options.png)
6. When you finish modifying, click **Save** in the upper right corner.
7. Open the project file, go to ![](figure/deveco-device-toollogo.png) \> **PROJECT TASKS** \> **hi3518ev300\_fastboot** \> **Erase** to erase U-Boot.
7. Open the project file, go to ![](figures/hi3518-deveco-device-tool-logo.png) \> **PROJECT TASKS** \> **hi3518ev300\_fastboot** \> **Erase** to erase U-Boot.
![](figure/erase-u-boot.png)
![](figures/erase-u-boot.png)
8. When the following message is displayed, power off the development board and then power it on.
![](figure/restart-the-development-board-12.png)
![](figures/hi3518-restart-the-development-board.png)
9. If the following message is displayed, it indicates that U-Boot is erased successfully.
![](figure/u-boot-erased-successfully.png)
![](figures/u-boot-erased-successfully.png)
10. Go to **hi3518ev300** \> **Upload** to start programming.
10. Go to **hi3518ev300** \> **Upload** to start burning.
![](figure/upload-13.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If this is the first time you burn the Hi3516D V300 or Hi3518E V300 board, the message "not find the Devices" may be displayed. In this case, follow the steps in [Installing the USB Driver on the Hi3516 or Hi3518 Series Development Boards](https://device.harmonyos.com/en/docs/ide/user-guides/usb_driver-0000001058690393) and start burning again.
![](figures/hi3518-upload.png)
11. If the following message is displayed, it indicates that the programming is successful.
11. If the following message is displayed, it indicates that the burning is successful.
![](figure/burning-succeeded-14.png)
![](figures/hi3518-burning-succeeded.png)
12. When the burning is successful, perform the operations in Running an Image to start the system.
## Running an Image<a name="section17612105814480"></a>
After programming is completed, you need to configure the bootloader to run the OpenHarmony system.
After burning is completed, you need to configure the bootloader to run the OpenHarmony system.
1. In the Hi3518E V300 task, click **Configure bootloader \(Boot OS\)** to configure the bootloader.
> ![](../public_sys-resources/icon-note.gif) **NOTE:**
> The bootloader configuration in DevEco Device Tool has been adapted to Hi3518E V300. Therefore, no manual modification is needed.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The bootloader configuration in DevEco Device Tool has been adapted to Hi3518E V300. Therefore, no manual modification is needed.
![](D:/IDP%E5%8F%91%E5%B8%83%E4%BB%B6/220/For%20OpenHarmony2.0/en/quick-start/figures/3518_bootloader.png)
![](figures/hi3518-bootloader.png)
2. When the message shown below is displayed, restart the development board. If **SUCCESS** is displayed, it indicates that the configuration is successful.
![](figure/3518_reset_success.png)
![](figures/hi3518-reset-success.png)
3. Click **Monitor** on the taskbar to start the serial port tool.
![](figure/3518_monitor.png)
![](figures/hi3518-monitor.png)
4. Follow the onscreen instructions until **OHOS \#** is displayed, indicating that the system is started successfully.
![](figure/3518_reboot_success.png)
![](figures/hi3518-reboot-success.png)
## Follow-up Learning<a name="section9712145420182"></a>
Congratulations! You have finished all steps! You are advised to go on learning how to develop [Cameras with a Screen](../guide/device-wlan-sdk.md).
Congratulations! You have finished all steps! You are advised to go on learning how to develop [Cameras with a Screen](../guide/device-iotcamera.md).
......@@ -19,8 +19,8 @@
The following figure shows the hardware connections.
**Figure 1** Hardware connections<a name="fig19272182991417"></a>
![](figure/hardware-connections-8.png "hardware-connections-8")
**Figure 1** Hi3518 hardware connections<a name="fig145521530134016"></a>
![](figures/hi3518-hardware-connections.png "hi3518-hardware-connections")
### Software<a name="section17315193935817"></a>
......
......@@ -15,27 +15,27 @@ If the Linux environment is installed using Docker, perform the building by refe
1. Open the HUAWEI DevEco Device Tool and choose **View** \> **Terminal**.
**Figure 1** Starting the IDE terminal tool<a name="fig755583241511"></a>
![](figure/starting-the-ide-terminal-tool.png "starting-the-ide-terminal-tool")
![](figures/starting-the-ide-terminal-tool.png "starting-the-ide-terminal-tool")
On the **TERMINAL** panel, run the ssh command, for example, **ssh** **_user_@_ipaddr_**, to connect to the Linux server.
**Figure 2** TERMINAL panel<a name="fig14407256101510"></a>
![](figure/terminal-panel.png "terminal-panel")
![](figures/terminal-panel.png "terminal-panel")
2. Go to the root directory of the code, run the **hb set** and **.** commands on the **TERMINAL** panel, and select the **wifiiot\_hispark\_pegasus** version.
**Figure 3** Selecting the target build version<a name="fig191035701814"></a>
![](figure/selecting-the-target-build-version.png "selecting-the-target-build-version")
![](figures/selecting-the-target-build-version.png "selecting-the-target-build-version")
3. Run the **hb build** command to start building.
**Figure 4** Running commands on the TERMINAL panel<a name="fig10635942111916"></a>
![](figure/running-commands-on-the-terminal-panel.png "running-commands-on-the-terminal-panel")
![](figures/running-commands-on-the-terminal-panel.png "running-commands-on-the-terminal-panel")
4. Check whether the building is successful. If yes, **wifiiot\_hispark\_pegasus build success** will be displayed, as shown in the following figure.
**Figure 5** Successful building<a name="fig195291328182015"></a>
![](figure/successful-building.png "successful-building")
![](figures/successful-building.png "successful-building")
5. Check whether the following files are generated in the **./out/wifiiot/** directory.
......@@ -44,19 +44,19 @@ If the Linux environment is installed using Docker, perform the building by refe
```
**Figure 6** Directory for storing the generated files<a name="fig112257131214"></a>
![](figure/directory-for-storing-the-generated-files.png "directory-for-storing-the-generated-files")
![](figures/directory-for-storing-the-generated-files.png "directory-for-storing-the-generated-files")
## Burning Images<a name="section3288165814218"></a>
Programming the flash memory is the process of downloading compiled program files to a chipset development board to provide a basis for subsequent debugging. With the one-click flash memory programming function of DevEco Device Tool, you can program flash memory on development boards quickly and efficiently.
Burning is the process of downloading compiled program files to a chipset development board to provide a basis for subsequent debugging. With the one-click burning function of DevEco Device Tool, you can burn development boards quickly and efficiently.
**The Hi3861 V100 development board allows you to program flash memory through the serial port using the burn-serial or hiburn-serial protocol. The hiburn-serial protocol is applicable to both Windows and Linux systems, while the burn-serial is applicable to Linux only.**
**You can burn to the Hi3861 V100 development board through the serial port using the burn-serial or hiburn-serial protocol. The hiburn-serial protocol is applicable to both Windows and Linux systems, while the burn-serial is applicable to Linux only.**
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The burn-serial protocol is used for compatibility with the projects of historical versions. It does not differ from hiburn-serial in operations.
The operations for programming flash memory in Windows and Linux are the same. The only difference lies in the environment setup for DevEco Device Tool.
The operations for burning in Windows and Linux are the same. The only difference lies in the environment setup for DevEco Device Tool.
1. Connect the PC and the target development board through the USB port. For details, see [Introduction to the Hi3861 Development Board](https://device.harmonyos.com/en/docs/start/introduce/oem_minitinier_des_3861-0000001105041324).
2. <a name="en-us_topic_0000001056563976_li848662117291"></a>Open Device Manager, then check and record the serial port number corresponding to the development board.
......@@ -64,33 +64,37 @@ The operations for programming flash memory in Windows and Linux are the same. T
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the serial port number is not displayed correctly, follow the steps described in [Installing the Serial Port Driver on the Hi3861 Series Development Board](https://device.harmonyos.com/en/docs/ide/user-guides/hi3861-drivers-0000001058153433).
![](figure/record-the-serial-port-number.png)
![](figures/hi3861-record-the-serial-port-number.png)
3. Open DevEco Device Tool and go to **Projects** \> **Settings**.
3. Open DevEco Device Tool, choose **QUICK ACCESS** \> **DevEco Home** \> **Projects**, and then click **Settings**.
![](figure/setting.png)
![](figures/hi3861-deveco-device-tool-setting.png)
4. On the **Partition Configuration** tab page, modify the settings. In general cases, you can leave the fields at their default settings.
5. On the **hi3861** tab page, set the programming options.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the file to be burnt is obtained by copying, you must manually change the path of the file to be burnt: Click the tab of the file to be burnt, select **Partition\_bin** from the **New Option** drop-down list box in **Partition Settings**, and set the path of the file to be burnt in **Partition\_bin**.
5. On the **hi3861** tab page, set the burning options.
- **upload\_port**: Select the serial port number obtained in step [2](#en-us_topic_0000001056563976_li848662117291).
- **upload\_protocol**: Select the programming protocol. For Windows, set this parameter to **burn-serial** or **hiburn-serial**. For Linux, set this parameter to **hiburn-serial**.
- **upload\_partitions**: Select the file to be programmed. **hi3861\_app** is selected by default.
- **upload\_protocol**: Select the burning protocol. For Windows, set this parameter to **burn-serial** or **hiburn-serial**. For Linux, set this parameter to **hiburn-serial**.
- **upload\_partitions**: Select the files to be burnt. **hi3861\_app** is selected by default.
![](figure/options.png)
![](figures/options.png)
6. When you finish modifying, click **Save** in the upper right corner.
7. Open the project file. In the DevEco Device Tool window, go to **PROJECT TASKS** \> **hi3861** \> **Upload** to start programming.
7. Open the project file. In the DevEco Device Tool window, go to **PROJECT TASKS** \> **hi3861** \> **Upload** to start burning.
![](figure/upload.png)
![](figures/hi3861-upload.png)
8. When the following information is displayed, press the RST button on the development board to restart it.
![](figure/restart-the-development-board.png)
![](figures/hi3861-restart-the-development-board.png)
9. Start programming. If the following message is displayed, it indicates that the programming is successful.
9. If the following message is displayed, it indicates that the burning is successful.
![](figure/burning-succeeded.png)
![](figures/hi3861-burning-succeeded.png)
## Connecting WLAN Module to the Internet.<a name="section194671619167"></a>
......@@ -100,12 +104,12 @@ After completing version building and burning, do as follows to connect the WLAN
1. Click the icon of **DevEco: Serial Monitor** at the bottom of DevEco Studio to keep the connection between the Windows workstation and the WLAN module.
**Figure 7** Opening the DevEco serial port<a name="fig464411253297"></a>
![](figure/opening-the-deveco-serial-port.png "opening-the-deveco-serial-port")
![](figures/opening-the-deveco-serial-port.png "opening-the-deveco-serial-port")
2. Reset the WLAN module. The message **ready to OS start** is displayed on the **TERMINAL** panel, indicating that the WLAN module is started successfully.
**Figure 8** Successful resetting of the WLAN module <a name="fig3327108143016"></a>
![](figure/successful-resetting-of-the-wlan-module.png "successful-resetting-of-the-wlan-module")
![](figures/successful-resetting-of-the-wlan-module.png "successful-resetting-of-the-wlan-module")
3. Run the following AT commands in sequence via the DevEco serial port terminal to start the STA mode, connect to the specified AP, and enable Dynamic Host Configuration Protocol \(DHCP\).
......@@ -126,6 +130,6 @@ After completing version building and burning, do as follows to connect the WLAN
```
**Figure 9** Successful networking of the WLAN module<a name="fig7672858203010"></a>
![](figure/successful-networking-of-the-wlan-module.png "successful-networking-of-the-wlan-module")
![](figures/successful-networking-of-the-wlan-module.png "successful-networking-of-the-wlan-module")
......@@ -9,6 +9,7 @@
- [What should I do when the message Could not find a version that satisfies the requirement six\>=1.9.0 is displayed during compilation and building?](#section4498158162320)
- [What should I do when the message cannot find -lgcc is displayed during compilation and building?](#section11181036112615)
- [What should I do when the message indicating Python cannot be found is displayed during compilation and building?](#section1571810194619)
- [What should I do when the message indicating Python cannot be found is displayed during compilation and building?](#section108385316482)
- [What should I do when an error with lsb\_release occurs during kconfiglib installation?](#section691681635814)
## What should I do when the message **configure: error: no acceptable C compiler found in $PATH** is displayed during Python 3 installation?<a name="section1221016541119"></a>
......@@ -60,7 +61,7 @@
The following error occurs during Python 3 installation:
```
zipimport.ZipImportError: can't decompress data; zlib not avaliable
zipimport.ZipImportError: can't decompress data; zlib not available
```
- **Possible Causes**
......@@ -73,7 +74,7 @@
Solution 2: If the software source does not contain **zlib**, download the source code from [http://www.zlib.net/](http://www.zlib.net/).
![](figure/download-zlib.png)
![](figures/download-zlib.png)
Then run the following commands to install **zlib** offline:
......@@ -134,7 +135,7 @@
- Download the source code from [https://pypi.org/project/pycrypto/\#files](https://pypi.org/project/pycrypto/#files).
![](figure/download-the-source-code.png)
![](figures/download-the-source-code.png)
- Save the source code package to the Linux server, decompress the package, and run the **python3 setup.py install** command to install **Crypto**.
- Rebuild an environment.
......@@ -164,7 +165,7 @@
- Download the installation package from [https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files).
![](figure/download-ecdsa.png)
![](figures/download-ecdsa.png)
- Save the installation package to the Linux server and run the **pip3 install ecdsa-0.15-py2.py3-none-any.whl** command to install **ecdsa**.
- Rebuild an environment.
......@@ -194,7 +195,7 @@
- Download the installation package from [https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files).
![](figure/download-six.png)
![](figures/download-six.png)
- Save the source code to the Linux server and run the **pip3 install six-1.14.0-py2.py3-none-any.whl** command to install **six**.
- Rebuild an environment.
......@@ -243,11 +244,11 @@
- **Possible Cause 1:** Python is not installed.
- **Solutions**
Install Python as instructed in [Installing and Configuring Python](quickstart-lite-env-setup-linux.md#section1238412211211).
[Install Python](../quick-start/quickstart-lite-env-setup-linux.md).
- **Possible Cause 2:** The soft link that points to the Python does not exist in the **usr/bin** directory.
![](figure/reason-2.png)
![](figures/reason-no-python-soft-link.png)
- **Solutions**
......@@ -262,7 +263,23 @@
Example:
![](figure/solution.png)
![](figures/solution-add-soft-link.png)
## What should I do when the message indicating Python cannot be found is displayed during compilation and building?<a name="section108385316482"></a>
- **Symptom**
![](figures/11.png)
- **Possible Causes**
Python 3 is not installed.
- **Solutions**
[Install Python](../quick-start/quickstart-lite-env-setup-linux.md).
## What should I do when an error with **lsb\_release** occurs during **kconfiglib** installation?<a name="section691681635814"></a>
......
......@@ -136,7 +136,7 @@ To parse the call stack information, the **Hi3861\_wifiiot\_app.asm** file is
3. Based on the above call stack information, it can be determined that an exception occurs in the **WadRecvCB** function.
![](figure/wadrecvcb-function.png)
![](figures/wadrecvcb-function.png)
4. Check and modify the code.
......
......@@ -23,8 +23,8 @@
The following figure shows the hardware connections.
**Figure 1** Hardware connections<a name="fig1922334410211"></a>
![](figure/hardware-connections.png "hardware-connections")
**Figure 1** Hi3861 hardware connections<a name="fig285519359396"></a>
![](figures/hi3861-hardware-connections.png "hi3861-hardware-connections")
### Software<a name="section727451210318"></a>
......@@ -124,7 +124,7 @@ sudo apt-get install build-essential gcc g++ make zlib* libffi-dev
```
**Figure 2** Successful installation \(SCons version requirement: 3.0.4 or later\)<a name="fig151441613316"></a>
![](figure/successful-installation-(scons-version-requirement-3-0-4-or-later).png "successful-installation-(scons-version-requirement-3-0-4-or-later)")
![](figures/successful-installation-(scons-version-requirement-3-0-4-or-later).png "successful-installation-(scons-version-requirement-3-0-4-or-later)")
### Installing Python Modules<a name="section88701892341"></a>
......@@ -220,13 +220,13 @@ sudo apt-get install build-essential gcc g++ make zlib* libffi-dev
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>- The Hi3861 platform supports only the static link of the libgcc library. The dynamic link is not recommended because version 3 of the GNU General Public License \(GPLv3\) will be polluted during commercial distribution.
>- Steps 2 to 15 of the following procedure are used to build the **gcc\_riscv32** image. You can simply [download the image](https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz) and skip these steps.
>- Steps 2 to 15 of the following procedure are used to build the **gcc\_riscv32** image. You can and skip these steps and directly [download the image](https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz).
1. Start a Linux server.
2. Install the **GCC**, **G++**, **Bison**, **Flex**, **Makeinfo** tools to ensure that the toolchain can be correctly compiled.
```
sudo apt-get install gcc && sudo apt-get install g++ && sudo apt-get install flex bison && sudo apt-get install texinfo
sudo apt-get install gcc g++ flex bison texinfo
```
3. Download the RISC-V GNU toolchain.
......@@ -353,6 +353,6 @@ Perform the following operations on the Windows station.
2. Install the driver.
3. After the driver is installed, remove and then insert the USB cable. The serial port entry should be displayed as shown in the following figure.
![](figure/serial-port-entry.png)
![](figures/serial-port-entry.png)
# Burning Images<a name="EN-US_TOPIC_0000001153557088"></a>
- [Prerequisites](#section232415263110)
- [Programming Flash Memory Through the Network Port](#section998903784810)
- [Prerequisites](#section18547185418328)
- [Programming Flash Memory Through the Network Port](#section1965361953312)
Burning of a regular system requires DevEco Device Tool v2.2 Beta1 or later.
Programming flash memory of a regular system requires DevEco Device Tool v2.2 Beta1 or later.
Hi3516D V300 supports burning of the standard system through the USB port, network port, or serial port, where:
Hi3516D V300 supports programming flash memory of the standard system through the USB port, network port, or serial port, where:
- **Windows system: Supports burning through the USB port, serial port, or network port**
- **Linux system: Supports burning through the network port or serial port**
- **Windows system: Supports programming through the USB port, serial port, or network port**
- **Linux system: Supports programming through the network port or serial port**
Except for environment setup, the operations of programming are the same for Windows and Linux.
Except for environment setup, the operations of burning are the same for Windows and Linux.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Currently, the Hi3516D V300 development board supports system burning over the network port, USB port, or serial port. This document uses the network port as an example. For details about system burning over other ports, see [Programming Flash Memory on Hi3516D V300](https://device.harmonyos.com/en/docs/ide/user-guides/hi3516_upload-0000001052148681).
>Currently, the Hi3516D V300 development board supports programming flash memory of the standard system through the USB port, network port, or serial port. This document uses the network port as an example. For details about programming flash memory over other ports, see [Programming Flash Memory on Hi3516D V300](https://device.harmonyos.com/en/docs/ide/user-guides/hi3516_upload-0000001052148681).
## Prerequisites<a name="section232415263110"></a>
## Prerequisites<a name="section18547185418328"></a>
In DevEco Device Tool, select **Import Project** to open the folder where the target file is located. Set **MCU** to **Hi3516DV300** under **HiSilicon\_Arm\_Linux** and **Framework** to **Hb**.
In DevEco Device Tool, select **Import Project** to open the folder where the target file is located. Set **MCU** to **Hi3516DV300** under **HiSilicon\_Arm\_Linux** and **Framework** to **Ohos-sources** or **Hpm**.
![](figure/hisilicon-arm-linux.png)
![](figures/hisilicon-arm-linux.png)
### Programming Flash Memory Through the Network Port<a name="section998903784810"></a>
## Programming Flash Memory Through the Network Port<a name="section1965361953312"></a>
The Hi3516DV300 supports programming through the network port in Windows or Linux.
The Hi3516DV300 supports burning through the network port in Windows or Linux.
1. Connect the PC and the target development board through the serial port, network port, and power port. For details, see [Introduction to the Hi3516 Development Board](https://device.harmonyos.com/en/docs/start/introduce/oem_minitinier_des_3516-0000001152041033).
2. <a name="en-us_topic_0000001056443961_li1050616379507"></a>Open Device Manager, then check and record the serial port number corresponding to the development board.
......@@ -32,37 +31,42 @@ The Hi3516DV300 supports programming through the network port in Windows or Linu
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the serial port number is not displayed correctly, follow the steps described in [Installing the Serial Port Driver on the Hi3516 or Hi3518 Series Development Boards](https://device.harmonyos.com/en/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695).
![](figure/record-the-serial-port-number-1.png)
![](figures/hi3516-record-the-serial-port-number.png)
3. Open DevEco Device Tool and go to **Projects** \> **Settings**.
3. Open DevEco Device Tool, choose **QUICK ACCESS** \> **DevEco Home** \> **Projects**, and then click **Settings**.
![](figure/settings-2.png)
![](figures/hi3516-deveco-device-tool-setting.png)
4. On the **hi3516dv300** tab page, configure the programming options.
4. On the **hi3516dv300** tab page, configure the burning options.
- **upload\_port**: Select the serial port number obtained in step [2](#en-us_topic_0000001056443961_li1050616379507).
- **upload\_protocol**: Select the programming protocol **hiburn-net**.
- **upload\_protocol**: Select the burning protocol **hiburn-net**.
- **upload\_partitions**: Select the files to be burnt. By default, **fastboot**, **boot**, **updater**, **misc**, **system**, **vendor**, and **userdata** are burnt at the same time.
![](figure/upload-options-28.png)
![](figures/upload-options-2.png)
5. Check and set the IP address of the network adapter connected to the development board. For details, see [Setting the IP Address of the Network Port for Programming on Hi3516](https://device.harmonyos.com/en/docs/ide/user-guides/set_ipaddress-0000001141825075).
6. Set the IP address of the network port for programming:
5. <a name="en-us_topic_0000001056443961_li85106114532"></a>Check and set the IP address of the network adapter connected to the development board. For details, see [Setting the IP Address of the Network Port for Burning to Hi3516](https://device.harmonyos.com/en/docs/ide/user-guides/set_ipaddress-0000001141825075).
6. Set the IP address of the network port for burning:
- **upload\_net\_server\_ip**: Select the IP address set in step [6](en-us_topic_0000001056443961.md#li1558813168234), such as 192.168.1.2.
- **upload\_net\_client\_mask**: Set the subnet mask of the development board, such as 255.255.255.0. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated.
- **upload\_net\_client\_gw**: Set the gateway of the development board, such as 192.168.1.1. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated.
- **upload\_net\_client\_ip**: Set the IP address of the development board, such as 192.168.1.3. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated.
- **upload\_net\_server\_ip**: Select the IP address set in step [5](#en-us_topic_0000001056443961_li85106114532), such as 192.168.1.2.
- **upload\_net\_client\_mask**: Set the subnet mask of the development board, such as 255.255.255.0. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated. Example: 255.255.255.0.
- **upload\_net\_client\_gw**: Set the gateway of the development board, such as 192.168.1.1. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated. Example: 192.168.1.1.
- **upload\_net\_client\_ip**: Set the IP address of the development board, such as 192.168.1.3. Once the **upload\_net\_server\_ip** field is set, this field will be automatically populated. Example: 192.168.1.3.
![](figure/ip-address-information.png)
![](figures/ip-address-information-3.png)
7. When you finish modifying, click **Save** in the upper right corner.
8. When the following message is displayed, power off the development board and then power it on.
8. Open the project file and go to ![](figures/2021-01-27_170334.png) \> **PROJECT TASKS** \> **hi3516dv300** \> **Upload** to start burning.
![](figures/en-us_image_0000001215342695.png)
9. When the following message is displayed, power off the development board and then power it on.
![](figure/restart-the-development-board-3.png)
![](figures/hi3516-restart-the-development-board.png)
9. Start programming. If the following message is displayed, it indicates that the programming is successful.
10. If the following message is displayed, it indicates that the burning is successful.
![](figure/burning-succeeded-4.png)
![](figures/hi3516-burning-succeeded-net.png)
11. When the burning is successful, perform the operations in [Running an Image](https://device.harmonyos.com/en/docs/start/introduce/quickstart-standard-running-0000001142160948) to start the system.
# Setting Up Ubuntu Development Environment in Docker Mode<a name="EN-US_TOPIC_0000001119805112"></a>
# Setting Up a Ubuntu Development Environment in Docker Mode<a name="EN-US_TOPIC_0000001119805112"></a>
- [Obtaining Standard-System Source Code](#section8761819202511)
- [Prerequisites](#section102871547153314)
- [Procedure](#section429012478331)
- [Running prebuilts](#section0495320152619)
- [Obtaining the Docker Environment](#section181431248132513)
- [Building Source Code](#section92391739152318)
......@@ -19,7 +20,7 @@ The standard OpenHarmony system provides a Docker environment which encapsulates
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
3. Install the [git client](http://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading), and configure basic user information.
3. Install the [git client](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading), and configure basic user information.
```
git config --global user.name "yourname"
......@@ -38,13 +39,14 @@ The standard OpenHarmony system provides a Docker environment which encapsulates
### Procedure<a name="section429012478331"></a>
Two methods are provided for you to obtain the OpenHarmony master code. You are advised to create a new folder and run the related commands in this folder to download the source code. This folder will then be the root directory of the source code.
Method 1 \(recommended\): Use the **repo** tool to download the source code over SSH. \(You must have registered an SSH public key for access to Gitee.\)
```
repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
bash build/prebuilts_download.sh
```
Method 2: Use the **repo** tool to download the source code over HTTPS.
......@@ -53,9 +55,18 @@ Method 2: Use the **repo** tool to download the source code over HTTPS.
repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
```
## Running prebuilts<a name="section0495320152619"></a>
Go to the root directory of the source code and run the following script to install the compiler and binary tool:
```
bash build/prebuilts_download.sh
```
By default, the downloaded prebuilts binary file is stored in **OpenHarmony\_2.0\_canary\_prebuilts** \(which is in the same directory as **OpenHarmony**\).
## Obtaining the Docker Environment<a name="section181431248132513"></a>
**Method 1: Obtaining the Docker image from HUAWEI CLOUD SWR**
......@@ -66,14 +77,14 @@ bash build/prebuilts_download.sh
docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.5
```
2. Go to the root directory of OpenHarmony code and run the following command to access the Docker build environment:
2. Go to the root directory of source code and run the following command to access the Docker build environment:
```
docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.5
```
**Method 2: Using the Dockerfile to build a local docker image**
**Method 2: Using the Dockerfile to Build a Local Docker Image**
1. Obtain the Dockerfile script for a local Docker image.
......@@ -88,7 +99,7 @@ bash build/prebuilts_download.sh
./build.sh
```
3. Go to the root directory of OpenHarmony code and run the following command to access the Docker build environment:
3. Go to the root directory of source code and run the following command to access the Docker build environment:
```
docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.5
......@@ -97,15 +108,15 @@ bash build/prebuilts_download.sh
## Building Source Code<a name="section92391739152318"></a>
1. Run the following script to start building for Standard-System Devices \(reference memory ≥ 128 MB\):
1. Run the following script to start building for standard-system devices \(reference memory ≥ 128 MB\).
```
./build.sh --product-name {product_name}
```
**product\_name** indicates the product supported by the current distribution, for example, **Hi3516DV300**.
**product\_name** indicates the platform supported by the current distribution, for example, Hi3516D V300.
Files generated during the build are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory.
Files generated during building are stored in the **out/ohos-arm-release/** directory, and the generated image is stored in the **out/ohos-arm-release/packages/phone/images/** directory.
2. Burn the image. For details, see [Burning Images](quickstart-standard-burn.md).
......
# FAQs<a name="EN-US_TOPIC_0000001166804465"></a>
- [What Should I Do If "ImportError: No module named apt\_pkg" Is Displayed During Compilation and Building?](#section32195464215)
## What Should I Do If "ImportError: No module named apt\_pkg" Is Displayed During Compilation and Building?<a name="section32195464215"></a>
- **Symptom**
The message "ImportError: No module named apt\_pkg" is displayed when an unidentifiable command is executed on the Linux server.
- **Possible Causes**
There is a compatibility issue of python3-apt.
......
......@@ -13,14 +13,14 @@ This document uses the recommended Hi3516D V300 development board as an example.
The following figure shows the process of getting started for the standard system, during which, you can set up the Ubuntu development environment in Docker mode or by using the installation package.
**Figure 1** Getting started for the standard system<a name="fig19162195553211"></a>
![](figure/getting-started-for-the-standard-system.png "getting-started-for-the-standard-system")
![](figures/getting-started-for-the-standard-system.png "getting-started-for-the-standard-system")
## Introduction to the Development Board<a name="en-us_topic_0000001053666242_section047719215429"></a>
Hi3516D V300 is a next-generation system on chip \(SoC\) designed for the industry-dedicated smart HD IP camera. It introduces a next-generation image signal processor \(ISP\), the H.265 video compression encoder, and a high-performance NNIE engine, leading the industry in terms of low bit rate, high image quality, intelligent processing and analysis, and low power consumption.
**Figure 2** Hi3516D V300 front view<a name="fig202901538183412"></a>
![](figure/hi3516d-v300-front-view-27.png "hi3516d-v300-front-view-27")
![](figures/hi3516d-v300-front-view-1.png "hi3516d-v300-front-view-1")
## Development Board Specifications<a name="en-us_topic_0000001053666242_section15192203316533"></a>
......@@ -40,7 +40,7 @@ Hi3516D V300 is a next-generation system on chip \(SoC\) designed for the indust
</tr>
<tr id="en-us_topic_0000001053666242_row21721687435"><td class="cellrowborder" valign="top" width="14.77%" headers="mcps1.2.3.1.1 "><p id="en-us_topic_0000001053666242_p817216810435"><a name="en-us_topic_0000001053666242_p817216810435"></a><a name="en-us_topic_0000001053666242_p817216810435"></a>External components</p>
</td>
<td class="cellrowborder" valign="top" width="85.22999999999999%" headers="mcps1.2.3.1.2 "><a name="en-us_topic_0000001053666242_ul179543016208"></a><a name="en-us_topic_0000001053666242_ul179543016208"></a><ul id="en-us_topic_0000001053666242_ul179543016208"><li>Ethernet port</li><li>Audio and video<a name="en-us_topic_0000001053666242_ul5941311869"></a><a name="en-us_topic_0000001053666242_ul5941311869"></a><ul id="en-us_topic_0000001053666242_ul5941311869"><li>One voice input</li><li>One mono (AC_L) output, connected to a 3 W power amplifier (LM4871)</li><li>Micro-HDMI (one HDMI 1.4)</li></ul>
<td class="cellrowborder" valign="top" width="85.22999999999999%" headers="mcps1.2.3.1.2 "><a name="en-us_topic_0000001053666242_ul179543016208"></a><a name="en-us_topic_0000001053666242_ul179543016208"></a><ul id="en-us_topic_0000001053666242_ul179543016208"><li>Ethernet port</li><li>Audio and video<a name="en-us_topic_0000001053666242_ul5941311869"></a><a name="en-us_topic_0000001053666242_ul5941311869"></a><ul id="en-us_topic_0000001053666242_ul5941311869"><li>One voice input</li><li>One mono output (AC_L), connected to a 3 W power amplifier (LM4871)</li><li>Micro-HDMI (one HDMI 1.4)</li></ul>
</li><li>Cameras<a name="en-us_topic_0000001053666242_ul924263620"></a><a name="en-us_topic_0000001053666242_ul924263620"></a><ul id="en-us_topic_0000001053666242_ul924263620"><li>Sensor IMX335</li><li>M12 lens with a focal length of 4 mm and an aperture of 1.8</li></ul>
</li><li>Display<a name="en-us_topic_0000001053666242_ul101471711667"></a><a name="en-us_topic_0000001053666242_ul101471711667"></a><ul id="en-us_topic_0000001053666242_ul101471711667"><li>2.35-inch LCD connector</li><li>5.5-inch LCD connector</li></ul>
</li><li>External components and interfaces<a name="en-us_topic_0000001053666242_ul089255556"></a><a name="en-us_topic_0000001053666242_ul089255556"></a><ul id="en-us_topic_0000001053666242_ul089255556"><li>microSD card interface</li><li>JTAG/I2S interface</li><li>ADC interface</li><li>Steer gear interface</li><li>Grove connector</li><li>USB 2.0 (Type C)</li><li>Three function keys: two custom keys and one update key</li><li>LED indicator (including green and red)</li></ul>
......
# Setting Up Ubuntu Development Environment with Installation Package<a name="EN-US_TOPIC_0000001119804790"></a>
# Setting Up a Ubuntu Development Environment Using the Installation Package<a name="EN-US_TOPIC_0000001119804790"></a>
- [Installing Dependent Tools](#section18431165519244)
- [Obtaining Standard-System Source Code](#section113751052102517)
......@@ -25,7 +25,7 @@ sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flex biso
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
3. Install the [git client](http://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading), and configure basic user information.
3. Install the [git client](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) and [git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading), and configure basic user information.
```
git config --global user.name "yourname"
......@@ -44,6 +44,8 @@ sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flex biso
### Procedure<a name="section429012478331"></a>
Two methods are provided for you to obtain the OpenHarmony master code. You are advised to create a new folder and run the related commands in this folder to download the source code. This folder will then be the root directory of the source code.
Method 1 \(recommended\): Use the **repo** tool to download the source code over SSH. \(You must have registered an SSH public key for access to Gitee.\)
```
......
# Running an Image<a name="EN-US_TOPIC_0000001142160948"></a>
## Running an Image
- [Running an Image](#section153991115191314)
- [Next](#section5600113114323)
## Running an Image<a name="section153991115191314"></a>
After the image burning is complete, perform the following steps to run the system:
......@@ -9,23 +12,23 @@ After the image burning is complete, perform the following steps to run the syst
1. In DevEco Device Tool, click **Monitor** to open the serial port tool.
![](figure/open-the-serial-port-tool.png)
![](figures/open-the-serial-port-tool.png)
2. Restart the development board. Before the autoboot countdown ends, press any key to enter the system.
![](figure/press-any-key-to-enter-the-system.gif)
![](figures/press-any-key-to-enter-the-system.gif)
3. Run the following commands to set system boot parameters:
```
setenv bootargs 'mem=640M console=ttyAMA0,115200 mmz=anonymous,0,0xA8000000,384M clk_ignore_unused androidboot.selinux=permissive skip_initramfs rootdelay=5 init=/init root=/dev/mmcblk0p5 rootfstype=ext4 rw blkdevparts=mmcblk0:1M(boot),15M(kernel),20M(updater),1M(misc),3307M(system),256M(vendor),-(userdata)'
setenv bootargs 'mem=640M console=ttyAMA0,115200 mmz=anonymous,0,0xA8000000,384M clk_ignore_unused rootdelay=10 hardware=Hi3516DV300 init=/init root=/dev/ram0 rw blkdevparts=mmcblk0:1M(boot),15M(kernel),20M(updater),2M(misc),3307M(system),256M(vendor),-(userdata)';
```
```
setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; bootm 0x80000000";
setenv bootcmd 'mmc read 0x0 0x82000000 0x800 0x4800; bootm 0x82000000'
```
![](figure/start.png)
![](figures/setenv-bootargs.png)
4. Save the parameter settings.
......@@ -33,7 +36,7 @@ After the image burning is complete, perform the following steps to run the syst
save
```
![](figure/save-the-parameter-settings.png)
![](figures/save-the-parameter-settings.png)
5. Restart the development board to start the system.
......@@ -41,8 +44,10 @@ After the image burning is complete, perform the following steps to run the syst
reset
```
![](figure/start-the-system.png)
![](figures/start-the-system.png)
## Next
## Next<a name="section5600113114323"></a>
Congratulations! You have completed the quick start for the standard system. Get yourself familiar with OpenHarmony by a [Development Example for Clock App](../guide/device-clock-guide.md).
# Setting Up Windows Development Environment<a name="EN-US_TOPIC_0000001124187462"></a>
# Setting Up a Windows Development Environment<a name="EN-US_TOPIC_0000001216019037"></a>
- [Obtaining the Software](#en-us_topic_0000001058091994_section1483143015558)
- [Installing Visual Studio Code](#en-us_topic_0000001058091994_section71401018163318)
- [Installing Python](#en-us_topic_0000001058091994_section16266553175320)
- [Installing Node.js](#en-us_topic_0000001058091994_section5353233124511)
- [Installing HPM](#en-us_topic_0000001058091994_section173054793610)
- [Installing the DevEco Device Tool Plug-in](#en-us_topic_0000001058091994_section4336315185716)
- [Installing DevEco Device Tool](#en-us_topic_0000001058091994_section10761564496)
System requirements:
- OS: 64-bit Windows 10
- User name: cannot contain Chinese characters
DevEco Device Tool is a plug-in for Visual Studio Code. The installation procedure includes five parts:
1. Installing Visual Studio Code
2. Installing Python
3. Installing Node.js
4. Installing HPM
5. Installing the DevEco Device Tool Plug-in
## Obtaining the Software<a name="en-us_topic_0000001058091994_section1483143015558"></a>
<a name="en-us_topic_0000001058091994_table12730195765616"></a>
<table><thead align="left"><tr id="en-us_topic_0000001058091994_row6730125785610"><th class="cellrowborder" valign="top" width="19.49%" id="mcps1.1.5.1.1"><p id="en-us_topic_0000001058091994_p1573065716561"><a name="en-us_topic_0000001058091994_p1573065716561"></a><a name="en-us_topic_0000001058091994_p1573065716561"></a>Tool</p>
</th>
<th class="cellrowborder" valign="top" width="20.5%" id="mcps1.1.5.1.2"><p id="en-us_topic_0000001058091994_p197306572566"><a name="en-us_topic_0000001058091994_p197306572566"></a><a name="en-us_topic_0000001058091994_p197306572566"></a>Description</p>
</th>
<th class="cellrowborder" valign="top" width="20.03%" id="mcps1.1.5.1.3"><p id="en-us_topic_0000001058091994_p373085711569"><a name="en-us_topic_0000001058091994_p373085711569"></a><a name="en-us_topic_0000001058091994_p373085711569"></a>Version</p>
</th>
<th class="cellrowborder" valign="top" width="39.98%" id="mcps1.1.5.1.4"><p id="en-us_topic_0000001058091994_p197309576566"><a name="en-us_topic_0000001058091994_p197309576566"></a><a name="en-us_topic_0000001058091994_p197309576566"></a>How to Obtain</p>
</th>
</tr>
</thead>
<tbody><tr id="en-us_topic_0000001058091994_row12730155765618"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p123931728135713"><a name="en-us_topic_0000001058091994_p123931728135713"></a><a name="en-us_topic_0000001058091994_p123931728135713"></a>Visual Studio Code</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p12332194816317"><a name="en-us_topic_0000001058091994_p12332194816317"></a><a name="en-us_topic_0000001058091994_p12332194816317"></a>Code editing tool</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p711918919618"><a name="en-us_topic_0000001058091994_p711918919618"></a><a name="en-us_topic_0000001058091994_p711918919618"></a>V1.53 or later (64-bit)</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p2721438193710"><a name="en-us_topic_0000001058091994_p2721438193710"></a><a name="en-us_topic_0000001058091994_p2721438193710"></a><a href="https://code.visualstudio.com/Download" target="_blank" rel="noopener noreferrer">https://code.visualstudio.com/Download</a></p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row187311257185619"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p21270444579"><a name="en-us_topic_0000001058091994_p21270444579"></a><a name="en-us_topic_0000001058091994_p21270444579"></a>Python</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p547205817316"><a name="en-us_topic_0000001058091994_p547205817316"></a><a name="en-us_topic_0000001058091994_p547205817316"></a>Programming tool</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p1991315166416"><a name="en-us_topic_0000001058091994_p1991315166416"></a><a name="en-us_topic_0000001058091994_p1991315166416"></a>V3.8.9 or later (64-bit)</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p108321457411"><a name="en-us_topic_0000001058091994_p108321457411"></a><a name="en-us_topic_0000001058091994_p108321457411"></a><a href="https://www.python.org/downloads/" target="_blank" rel="noopener noreferrer">https://www.python.org/downloads/</a></p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row117316576562"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p16405151165717"><a name="en-us_topic_0000001058091994_p16405151165717"></a><a name="en-us_topic_0000001058091994_p16405151165717"></a>Node.js</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p1773185765616"><a name="en-us_topic_0000001058091994_p1773185765616"></a><a name="en-us_topic_0000001058091994_p1773185765616"></a>The npm environment provider</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p16304104120181"><a name="en-us_topic_0000001058091994_p16304104120181"></a><a name="en-us_topic_0000001058091994_p16304104120181"></a>Any of the following versions:</p>
<a name="en-us_topic_0000001058091994_ul875854471719"></a><a name="en-us_topic_0000001058091994_ul875854471719"></a><ul id="en-us_topic_0000001058091994_ul875854471719"><li>V12.22.5 or later (64-bit)</li><li>V14.17.5 or later (64-bit)</li><li>V16.6.0 or later (64-bit)</li></ul>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p9200911141112"><a name="en-us_topic_0000001058091994_p9200911141112"></a><a name="en-us_topic_0000001058091994_p9200911141112"></a><a href="https://nodejs.org/en/download/" target="_blank" rel="noopener noreferrer">https://nodejs.org/en/download/</a></p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row6731105715561"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p2081865318571"><a name="en-us_topic_0000001058091994_p2081865318571"></a><a name="en-us_topic_0000001058091994_p2081865318571"></a>HPM</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p1632215161040"><a name="en-us_topic_0000001058091994_p1632215161040"></a><a name="en-us_topic_0000001058091994_p1632215161040"></a>Package manager</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p773185715566"><a name="en-us_topic_0000001058091994_p773185715566"></a><a name="en-us_topic_0000001058091994_p773185715566"></a>V1.3.0 or later</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p14731125745610"><a name="en-us_topic_0000001058091994_p14731125745610"></a><a name="en-us_topic_0000001058091994_p14731125745610"></a>For details, see <a href="#en-us_topic_0000001058091994_section173054793610">Installing HPM</a>.</p>
</td>
</tr>
<tr id="en-us_topic_0000001058091994_row13317205645717"><td class="cellrowborder" valign="top" width="19.49%" headers="mcps1.1.5.1.1 "><p id="en-us_topic_0000001058091994_p143411112587"><a name="en-us_topic_0000001058091994_p143411112587"></a><a name="en-us_topic_0000001058091994_p143411112587"></a>DevEco Device Tool</p>
</td>
<td class="cellrowborder" valign="top" width="20.5%" headers="mcps1.1.5.1.2 "><p id="en-us_topic_0000001058091994_p1690316506517"><a name="en-us_topic_0000001058091994_p1690316506517"></a><a name="en-us_topic_0000001058091994_p1690316506517"></a>Plug-in for the OpenHarmony source code compilation, programming, and debugging</p>
</td>
<td class="cellrowborder" valign="top" width="20.03%" headers="mcps1.1.5.1.3 "><p id="en-us_topic_0000001058091994_p113171956185715"><a name="en-us_topic_0000001058091994_p113171956185715"></a><a name="en-us_topic_0000001058091994_p113171956185715"></a>V2.2 Beta2</p>
</td>
<td class="cellrowborder" valign="top" width="39.98%" headers="mcps1.1.5.1.4 "><p id="en-us_topic_0000001058091994_p3503163074720"><a name="en-us_topic_0000001058091994_p3503163074720"></a><a name="en-us_topic_0000001058091994_p3503163074720"></a><a href="https://device.harmonyos.com/cn/ide#download_beta" target="_blank" rel="noopener noreferrer">https://device.harmonyos.com/cn/ide#download_beta</a></p>
<p id="en-us_topic_0000001058091994_p23171856135717"><a name="en-us_topic_0000001058091994_p23171856135717"></a><a name="en-us_topic_0000001058091994_p23171856135717"></a>Log in with your HUAWEI ID to download it. You can <a href="https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148" target="_blank" rel="noopener noreferrer">register an account here</a>.</p>
</td>
</tr>
</tbody>
</table>
## Installing Visual Studio Code<a name="en-us_topic_0000001058091994_section71401018163318"></a>
## Installing DevEco Device Tool<a name="en-us_topic_0000001058091994_section10761564496"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you have installed Visual Studio Code, open the CLT and run **code --version** to check whether the version is 1.53 or later. If the version number is returned, it indicates that the environment variables are set correctly.
1. Double-click the Visual Studio Code package to install it. During the installation, select **Add to PATH \(requires shell restart\)**.
![](figure/installing-visual-studio-code.png)
2. After the installation is complete, open the CLT and run **code --version**. If the version number can be displayed, it indicates that the installation is successful.
## Installing Python<a name="en-us_topic_0000001058091994_section16266553175320"></a>
1. Double-click the Python software package, select **Add Python 3.8 to PATH**, and click **Install Now**.
![](figure/installing-python.png)
2. After the installation is complete, click **Close**.
DevEco Device Tool is installed in Visual Studio Code as a plug-in and depends on Python, Node.js, and HPM for running.
![](figure/setup-was-successful.png)
3. Open the CLT, and run **python --version** to check the installation result.
![](figure/checking-the-installation-result.png)
4. In the CLT, run the following commands to set the pip source for downloading the dependencies required for later installation:
```
pip config set global.trusted-host repo.huaweicloud.com
pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple
pip config set global.timeout 120
```
## Installing Node.js<a name="en-us_topic_0000001058091994_section5353233124511"></a>
DevEco Device Tool supports integrated installation. The DevEco Device Tool setup wizard checks whether the adaptation versions of Visual Studio Code, Python, Node.js and HPM tools have been installed. If any of the tools is not installed, you'll be prompted to select the tool to be automatically installed.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you have installed Node.js, open the CLT and run **node -v** to check whether the version is 12.0.0 or later.
1. Run the downloaded software package to install. Use the default settings when following the installation wizard, and click **Next** until **Finish** is displayed. During the installation, Node.js will automatically set the system Path environment variable to the installation directory of **node.exe**.
2. Open the CLT and run **node -v**. If the version number of Node.js is displayed, it indicates that Node.js has been successfully installed.
>Before installing DevEco Device Tool, make sure the user name of the host does not contain Chinese characters. Otherwise, the **DevEco Home** page will be stuck loading and the DevEco Device Tool cannot work.
## Installing HPM<a name="en-us_topic_0000001058091994_section173054793610"></a>
1. Log in to the [HarmonyOS Device website](https://device.harmonyos.com/cn/ide#download_beta) with your HUAWEI ID and download DevEco Device Tool V3.0 Beta1 or a later version. If you do not have a HUAWEI ID, [register](https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148) one first.
2. Decompress the DevEco Device Tool package, double-click the installer, and then click **Next**.
3. Set the installation path of DevEco Device Tool and click **Next**.
4. When prompted, select the tools to be automatically installed and click **Next**.
Before installing HPM, ensure that Node.js has been installed
![](figures/snap28.png)
and that your network can access the Internet. If your network requires a proxy to access the Internet, [set up the npm proxy](https://device.harmonyos.com/en/docs/ide/user-guides/npm_proxy-0000001054491032) first.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If HPM has been installed, run **npm update -g @ohos/hpm-cli** to update it to the latest version.
1. You are advised to set the npm source to an image in China, for example, a HUAWEI CLOUD image source.
```
npm config set registry https://repo.huaweicloud.com/repository/npm/
```
2. Open the CLT and run the following command to install the latest version of HPM:
```
npm install -g @ohos/hpm-cli
```
![](figure/hpm-version.png)
3. After the installation is complete, run the following command to obtain the installation result:
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>When the setup wizard detects that a compatible Python version has been installed, it prompts you to select the installed Python version or download the recommended Python version.
```
hpm -V
```
5. In the dialog box shown below, click **Next** to download and install the tools.
![](figures/snap8.png)
## Installing the DevEco Device Tool Plug-in<a name="en-us_topic_0000001058091994_section4336315185716"></a>
6. In the displayed Python setup wizard, select **Add Python 3.8 to PATH** and click **Install Now**. After the installation is complete, click **Close**.
Before installing DevEco Device Tool, make sure the user name of the host does not contain Chinese characters. Otherwise, the **DevEco Home** page will be stuck loading and the DevEco Device Tool cannot work.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you have selected the compatible Python version installed on your device, the Python setup wizard will not be displayed. In this case, you skip this step.
>If DevEco Device Tool 2.1 Release is installed, the Python version must be 3.8.x. If DevEco Device Tool V3.0 Beta1 or a later version is installed, the Python version must be 3.8.x or 3.9.x.
DevEco Device Tool will automatically download and install the C/C++ and CodeLLDB plug-ins from the Visual Studio Code Marketplace during the installation process. Therefore, make sure Visual Studio Code can access the Internet. If your network requires a proxy to access the Internet, [set up the Visual Studio Code proxy](https://device.harmonyos.com/en/docs/ide/user-guides/vscode_proxy-0000001074231144) first.
![](figures/snap34.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Before installing DevEco Device Tool, ensure that Visual Studio Code is closed.
1. Decompress the DevEco Device Tool plug-in package and double-click the installer to install.
2. DevEco Device Tool checks whether the toolkit on which the installation depends meets the requirements. If the requirements are not met, follow the preceding installation instructions in this section.
7. In the Visual Studio Code setup wizard, install Visual Studio Code as prompted. During the installation, select **Add to PATH \(requires shell restart\)**.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If Visual Studio Code has been installed but fails to be detected, restart your computer.
>If you are using the correct version of Visual Studio Code, the Visual Studio Code setup wizard will not be displayed. In this case, you skip this step.
![](figure/installing-the-deveco-device-tool.png)
![](figures/snap33.png)
3. Click **Install**.
8. In the Node.js setup wizard, retain the default settings and click **Next** until **Finish** is displayed. During the installation, Node.js will automatically set the system Path environment variable to the installation directory of **node.exe**.
![](figure/install.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you are using the correct version of Node.js, the Node.js setup wizard will not be displayed. In this case, you skip this step.
4. After the installation is complete, click **Close**.
9. Wait for the DevEco Device Tool setup wizard to automatically install the HPM and DevEco Device Tool. After the installation is complete, click **Finish** to close the setup wizard.
![](figure/installation-complete.png)
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you are using the correct version of HPM, the setup wizard does not download or install HPM.
5. Start Visual Studio Code. The C/C++ and CodeLLDB plug-ins on which DevEco Device Tool depends will be automatically installed. After the installation is complete, click ![](figure/button.png)on the left of Visual Studio Code to check whether C/C++, CodeLLDB, and DevEco Device Tool are included in the INSTALLED list.
10. Start Visual Studio Code. The C/C++ and CodeLLDB plug-ins on which DevEco Device Tool depends will be automatically installed. After the installation is complete, click ![](figures/button.png) on the left of Visual Studio Code to check whether C/C++, CodeLLDB, and DevEco Device Tool are included in the **INSTALLED** list.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the C/C++ and CodeLLDB plug-ins fail to be installed, DevEco Device Tool cannot run properly. To solve the issue, see [Installing the C/C++ and CodeLLDB Plug-ins Offline](https://device.harmonyos.com/en/docs/ide/user-guides/offline_plugin_install-0000001074376846).
![](figure/visual-studio-code.png)
![](figures/deveco-device-tool-install-sucessful.png)
......@@ -2,11 +2,11 @@
- **[Introduction](quickstart-standard-overview.md)**
- **[Setting Up Windows Development Environment](quickstart-standard-windows-environment.md)**
- **[Setting Up a Windows Development Environment](quickstart-standard-windows-environment.md)**
- **[Setting Up Ubuntu Development Environment in Docker Mode](quickstart-standard-docker-environment.md)**
- **[Setting Up a Ubuntu Development Environment in Docker Mode](quickstart-standard-docker-environment.md)**
- **[Setting Up Ubuntu Development Environment with Installation Package](quickstart-standard-package-environment.md)**
- **[Setting Up a Ubuntu Development Environment Using the Installation Package](quickstart-standard-package-environment.md)**
- **[Burning Images](quickstart-standard-burn.md)**
......
......@@ -49,6 +49,9 @@
- [Development Guidelines](subsys-application-framework-guide.md)
- [Development Example](subsys-application-framework-demo.md)
- [OTA Upgrade](subsys-ota-guide.md)
- [Telephony Service ](subsys-tel.md)
- [Telephony Service](telephony-service.md)
- [Development Guidelines](development-guidelines.md)
- [Security](subsys-security.md)
- [Overview](subsys-security-overview.md)
- [Development Guidelines on Application Signature Verification](subsys-security-sigverify.md)
......
# Development Guidelines<a name="EN-US_TOPIC_0000001167051994"></a>
- [Initializing a Modem Vendor Library](#section211mcpsimp)
- [When to Use](#section213mcpsimp)
- [Available APIs](#section811343241215)
- [How to Develop](#section51031144122)
- [Debugging and Verification](#section5351151517132)
- [Responding to Modem Service Requests](#section295mcpsimp)
- [When to Use](#section297mcpsimp)
- [Available APIs](#section9503155219134)
- [How to Develop](#section17190412101414)
- [Debugging and Verification](#section10207938171413)
- [Reporting Modem Events](#section390mcpsimp)
- [When to Use](#section401mcpsimp)
- [Available APIs](#section191193791518)
- [How to Develop](#section16394112401512)
- [Debugging and Verification](#section16999174401516)
- [Development Examples](#section33444350167)
- [Integrating Modem Vendor Libraries](#section590mcpsimp)
- [Configuring Compilation Information](#section592mcpsimp)
- [Debugging and Verification](#section620mcpsimp)
## Initializing a Modem Vendor Library<a name="section211mcpsimp"></a>
### When to Use<a name="section213mcpsimp"></a>
Initializing a modem vendor library means to implement **const HRilOps \*RilInitOps\(const struct HRilReport \*reportOps\)** function in the vendor library. This function is mainly used to:
- Receive function pointers to event callbacks of RIL Adapter. When a service event needs to be reported, the target pointer will be called to report the event to RIL Adapter.
- Create a thread for reading modem nodes. In this thread, the data reported by the modem is read cyclically and parsed as a specific service event for reporting.
- Return the function pointer of the service request API to RIL Adapter.
### Available APIs<a name="section811343241215"></a>
The following table describes the API for initializing a modem vendor library.
**Table 1** API for initializing a modem vendor library
<a name="table223mcpsimp"></a>
<table><thead align="left"><tr id="row229mcpsimp"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p231mcpsimp"><a name="p231mcpsimp"></a><a name="p231mcpsimp"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.2"><p id="p233mcpsimp"><a name="p233mcpsimp"></a><a name="p233mcpsimp"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row235mcpsimp"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p237mcpsimp"><a name="p237mcpsimp"></a><a name="p237mcpsimp"></a>const HRilOps *RilInitOps(const struct HRilReport * reportOps)</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p239mcpsimp"><a name="p239mcpsimp"></a><a name="p239mcpsimp"></a>Function: Provides an entry for running a modem vendor library.</p>
<p id="p56281836194610"><a name="p56281836194610"></a><a name="p56281836194610"></a>Input parameter:</p>
<p id="p240mcpsimp"><a name="p240mcpsimp"></a><a name="p240mcpsimp"></a><strong id="b164737479278"><a name="b164737479278"></a><a name="b164737479278"></a>reportOps</strong>: Specifies the pointer to the event callback function, which is passed by RIL Adapter.</p>
<p id="p241mcpsimp"><a name="p241mcpsimp"></a><a name="p241mcpsimp"></a>Return result: function pointer of the service request API.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section51031144122"></a>
1. Set the event callback function pointers passed by RIL Adapter through **RilInitOps**.
```
// Define the callback function pointers of the modem vendor library.
static struct HRilReport g_reportOps = {
OnCallReport, // Callback function for call services
OnDataReport, // Callback function for cellular data services
OnModemReport, // Callback function for modem services
OnNetworkReport, // Callback function for network search services
OnSimReport, // Callback function for SIM card services
OnSmsReport // Callback function for SMS services
};
```
1. Create the **g\_reader** main thread to enable message looping.
```
pthread_attr_t t;
pthread_attr_init(&t);
pthread_attr_setdetachstate(&t, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&g_reader, &t, ReaderLoop, &t); // Create the g_reader thread.
```
1. In the **g\_eventListeners** thread, use **open\(\)** to open a modem node and then create the **g\_reader** thread to read and process messages reported by the modem.
```
g_fd = open(g_devicePath, O_RDWR); // Open the device node specified by g_devicePath.
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&g_eventListeners, &attr, EventListeners, NULL);
```
1. Return the function pointer of the service request API.
```
// Structure for the service request API of the call module
typedef struct {
// Obtain the call list.
void (*GetCallList)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
// Make a call.
void (*Dial)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
// Disconnect a call.
void (*Hangup)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
// Reject a call.
void (*Reject)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
// Answer a call.
void (*Answer)(ReqDataInfo *requestInfo, const void *data, size_t dataLen);
} HRilCallReq;
// Callback function pointers of the call module
static const HRilCallReq g_callReqOps = {
.GetCallList = ReqGetCallList, // Obtain the call list.
.Dial = ReqDial, // Make a call.
.Hangup = ReqHangup, // Disconnect a call.
.Reject = ReqReject, // Reject a call.
.Answer = ReqAnswer, // Answer a call.
};
// Service request structure
typedef struct {
const HRilCallReq *callOps; // Pointer to the structure of call service requests
const HRilSimReq *simOps; // Pointer to the structure of SIM card service requests
const HRilSmsReq *smsOps; // Pointer to the structure of SMS and MMS service requests
const HRilDataReq *dataOps; // Pointer to the structure of cellular data service requests
const HRilNetworkReq *networkOps; // Pointer to the structure of network search service requests
const HRilModemReq *modemOps; // Pointer to the structure of modem service requests
} HRilOps;
// Service request APIs
HRilOps g_hrilOps = {
.callOps = &g_callReqOps, // API for call service requests
.simOps = &g_simReqOps, // API for SIM card service requests
.smsOps = &g_smsReqOps, // API for SMS and MMS service requests
.networkOps = &g_networkReqOps, // API for cellular data service requests
.dataOps = &g_dataReqOps, // API for network search service requests
.modemOps = &g_modemReqOps, // API for modem service requests
};
```
### Debugging and Verification<a name="section5351151517132"></a>
1. Use the [hdc\_std](en-us_topic_0000001080478129.md#section05992022154916) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device. For details about how to integrate a library file, see [Integrating Modem Vendor Libraries](#section590mcpsimp).
```
hdc_std file send libril_vendor.z.so /system/lib/
```
2. Reboot the debugging device.
```
hdc_std shell sync
hdc_std shell reboot
```
3. Run the **hdc\_std shell hilog** command to view the debug log, and check whether the **RilInitOps\(\)** function is successfully executed. The following debug log is for reference:
```
01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [RilAdapterDispatch-(hril_hdf.c:55)] sbuf IPC obtain test success!
01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [LoadVendor-(hril_hdf.c:33)] RilInit rilInit start
01-01 05:13:23.071 136 2319 D 00000/RilAdapterInit: [LoadVendor -(hril_hdf.c:45)] RilInit rilInit completed
```
## Responding to Modem Service Requests<a name="section295mcpsimp"></a>
### When to Use<a name="section297mcpsimp"></a>
After receiving a specific telephony service request, RIL Adapter calls the target function pointer obtained in modem vendor library initialization to send a specific service request to the vendor library. Then, the vendor library processes the request based on the request ID.
### Available APIs<a name="section9503155219134"></a>
The following table describes the APIs for responding to modem service requests, with the dial module as an example.
**Table 2** APIs for responding to modem service requests
<a name="table303mcpsimp"></a>
<table><thead align="left"><tr id="row309mcpsimp"><th class="cellrowborder" valign="top" width="49.84%" id="mcps1.2.3.1.1"><p id="p311mcpsimp"><a name="p311mcpsimp"></a><a name="p311mcpsimp"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="50.160000000000004%" id="mcps1.2.3.1.2"><p id="p313mcpsimp"><a name="p313mcpsimp"></a><a name="p313mcpsimp"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row315mcpsimp"><td class="cellrowborder" valign="top" width="49.84%" headers="mcps1.2.3.1.1 "><p id="p317mcpsimp"><a name="p317mcpsimp"></a><a name="p317mcpsimp"></a>void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen);</p>
</td>
<td class="cellrowborder" valign="top" width="50.160000000000004%" headers="mcps1.2.3.1.2 "><p id="p319mcpsimp"><a name="p319mcpsimp"></a><a name="p319mcpsimp"></a>Function: Processes number dial requests.</p>
<p id="p12610151394115"><a name="p12610151394115"></a><a name="p12610151394115"></a>Input parameters:</p>
<a name="ul105511416204116"></a><a name="ul105511416204116"></a><ul id="ul105511416204116"><li><strong id="b85517162414"><a name="b85517162414"></a><a name="b85517162414"></a>requestInfo</strong>: request type</li></ul>
<a name="ul1676502416411"></a><a name="ul1676502416411"></a><ul id="ul1676502416411"><li><strong id="b1576510240416"><a name="b1576510240416"></a><a name="b1576510240416"></a>data</strong>: called number</li></ul>
<a name="ul842034134114"></a><a name="ul842034134114"></a><ul id="ul842034134114"><li><strong id="b1542193411415"><a name="b1542193411415"></a><a name="b1542193411415"></a>dataLen</strong>: data length</li></ul>
<p id="p323mcpsimp"><a name="p323mcpsimp"></a><a name="p323mcpsimp"></a>Return value: none</p>
</td>
</tr>
<tr id="row324mcpsimp"><td class="cellrowborder" valign="top" width="49.84%" headers="mcps1.2.3.1.1 "><p id="p326mcpsimp"><a name="p326mcpsimp"></a><a name="p326mcpsimp"></a>void (*OnCallReport)(struct ReportInfo reportInfo, const void *data, size_t dataLen);</p>
</td>
<td class="cellrowborder" valign="top" width="50.160000000000004%" headers="mcps1.2.3.1.2 "><p id="p328mcpsimp"><a name="p328mcpsimp"></a><a name="p328mcpsimp"></a>Function: Reports the execution result of a service request to RIL Adapter.</p>
<p id="p489264432"><a name="p489264432"></a><a name="p489264432"></a>Input parameters:</p>
<a name="ul44156301444"></a><a name="ul44156301444"></a><ul id="ul44156301444"><li><strong id="b15415930154418"><a name="b15415930154418"></a><a name="b15415930154418"></a>reportInfo</strong>: request type</li></ul>
<a name="ul18380115494513"></a><a name="ul18380115494513"></a><ul id="ul18380115494513"><li><strong id="b83808549457"><a name="b83808549457"></a><a name="b83808549457"></a>data</strong>: called number</li></ul>
<a name="ul118421156184517"></a><a name="ul118421156184517"></a><ul id="ul118421156184517"><li><strong id="b48421056144519"><a name="b48421056144519"></a><a name="b48421056144519"></a>dataLen</strong>: data length</li></ul>
<p id="p332mcpsimp"><a name="p332mcpsimp"></a><a name="p332mcpsimp"></a>Return value: none</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section17190412101414"></a>
1. Implement processing of dial requests in the **ReqDial\(\)** API.
```
// Implement the API for processing dial requests.
void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen)
{
HRilDial *pDial = NULL;
char cmd[MAX_BUFF_SIZE] = {0};
const char *clir = NULL;
int ret;
int err = HRIL_ERR_SUCCESS;
struct ReportInfo reportInfo = {};
ResponseInfo *pResponse = NULL;
if (data == NULL) {
TELEPHONY_LOGE("data is null!!!");
err = HRIL_ERR_INVALID_PARAMETER;
reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
OnCallReport(reportInfo, NULL, 0);
return;
}
pDial = (HRilDial *)data;
switch (pDial->clir) {
case CALL_CLIR_INVOCATION:
clir = "I";
break; /* invocation */
case CALL_CLIR_SUPPRESSION:
clir = "i";
break; /* suppression */
case CALL_CLIR_SUBSCRIPTION_DEFUALT:
default:
clir = "";
break; /* subscription default */
}
(void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir);
ret = SendCommandLock(cmd, NULL, 0, &pResponse); // Send the AT command.
......
}
```
2. After the modem executes the dial command, report the execution result to RIL Adapter via **OnCallReport\(\)**.
```
ret = SendCommandLock(cmd, NULL, 0, &pResponse);
if (ret != 0 || (pResponse != NULL && pResponse->success == 0)) {
TELEPHONY_LOGE("ATD send failed");
err = HRIL_ERR_GENERIC_FAILURE;
}
reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
```
### Debugging and Verification<a name="section10207938171413"></a>
1. Use the [hdc\_std](en-us_topic_0000001080478129.md#section05992022154916) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
```
hdc_std file send libril_vendor.z.so /system/lib/
```
2. Reboot the debugging device.
```
hdc_std shell sync
hdc_std shell reboot
```
3. Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function.
```
hdc_std shell
# ./system/bin/ril_adapter_test
----> Test Enter --------->Call---------------------
1----> RilUnitTest::OnRequestCallDialTest
2----> RilUnitTest:: OnRequestCallHangupTest
3----> RilUnitTest:: OnRequestCallAnswerTest
4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest
5----> RilUnitTest::OnRequestRefusedCallTest
1
```
4. Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **ReqDial\(\)** is successfully executed. The following debug log is for reference:
```
01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:210)] SendCommandLock enter, cmd: ATD17620373527
01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [SendCommandLock-(at_support.c:231)] SendCommandLock() command ATD17620373527
01-01 05:27:27.419 136 408 D 02b01/Rilvendor: [WriteATCommand-(channel.c:115)] WriteATCommand enter, cmd:ATD17620373527
01-01 05:27:27.421 136 187 D 02b01/Rilvendor: [ReadResponse-(channel.c:94)] g_bufferCur :
01-01 05:27:27.421 136 187 D 02b01/Rilvendor: OK
01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:144)] processLine line = OK
01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ReadResponse-(channel.c:81)] ReadResponse enter
01-01 05:27:27.422 136 187 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur:
01-01 05:27:27.422 136 187 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null
01-01 05:27:27.422 136 187 E 02b01/Rilvendor:^ORIG:1,0
01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:234)] processLine line = ^ORIG:1,0
01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(vendor_report.c:234)] enter to [^ORIG:1,0]: (null)
01-01 05:27:27.422 136 408 E 02b01/Rilvendor: [SendCommandLock-(at_support.c:264)] err = 0, cmd:ADT17620373527
```
## Reporting Modem Events<a name="section390mcpsimp"></a>
### When to Use<a name="section401mcpsimp"></a>
A modem node thread reads the messages reported by the modem cyclically, parses the messages into specific events, and then reports the events to RIL Adapter.
### Available APIs<a name="section191193791518"></a>
The following table describes the API for reporting modem events.
**Table 3** API for reporting modem events
<a name="table407mcpsimp"></a>
<table><thead align="left"><tr id="row413mcpsimp"><th class="cellrowborder" valign="top" width="52%" id="mcps1.2.3.1.1"><p id="p415mcpsimp"><a name="p415mcpsimp"></a><a name="p415mcpsimp"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="48%" id="mcps1.2.3.1.2"><p id="p417mcpsimp"><a name="p417mcpsimp"></a><a name="p417mcpsimp"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row419mcpsimp"><td class="cellrowborder" valign="top" width="52%" headers="mcps1.2.3.1.1 "><p id="p421mcpsimp"><a name="p421mcpsimp"></a><a name="p421mcpsimp"></a>void OnNotifyOps(const char *s, const char *smsPdu)</p>
</td>
<td class="cellrowborder" valign="top" width="48%" headers="mcps1.2.3.1.2 "><p id="p423mcpsimp"><a name="p423mcpsimp"></a><a name="p423mcpsimp"></a>Function: Distributes the events reported by the modem.</p>
<p id="p17924530141912"><a name="p17924530141912"></a><a name="p17924530141912"></a>Input parameters:</p>
<a name="ul678053915191"></a><a name="ul678053915191"></a><ul id="ul678053915191"><li><strong id="b14780173912196"><a name="b14780173912196"></a><a name="b14780173912196"></a>s</strong>: AT command prefix</li></ul>
<a name="ul206343434192"></a><a name="ul206343434192"></a><ul id="ul206343434192"><li><strong id="b65891958173518"><a name="b65891958173518"></a><a name="b65891958173518"></a>smsPdu</strong>: PDU of the SMS message</li></ul>
<p id="p426mcpsimp"><a name="p426mcpsimp"></a><a name="p426mcpsimp"></a>Return value: none</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section16394112401512"></a>
1. Call **OnNotifyOps\(\)** in the g\_reader thread of the modem device node to parse reported modem events. On determining the command type, call **OnXxxReport\(\)** to report the parsed module events to the hril layer.
```
// Parse the data reported by the modem as events proactively reported by the corresponding module.
void OnNotifyOps(const char *s, const char *smsPdu)
{
int ret = 0;
struct ReportInfo reportInfo = {0};
reportInfo.error = HRIL_ERR_SUCCESS;
reportInfo.type = HRIL_NOTIFICATION;
if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
return;
}
TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu);
// Determine the type of the proactively reported events based on the AT command.
if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") ||
ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") ||
ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) {
reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED;
OnCallReport(reportInfo, NULL, 0);
} else if (ReportStrWith(s, "+CMT:")) {
reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu));
}
// Report the events of each module to the hril layer.
...
}
```
1. Distribute the reported events from the **hril** layer to the Telephony Service layer.
```
// Report the call status proactively.
int32_t HRilCall::CallStateUpdated(
int32_t slotId, int32_t notifyType, const HRilErrno e, const void *response, size_t responseLen)
{
struct HdfSBuf *dataSbuf = HdfSBufTypedObtain(SBUF_IPC);
if (serviceCallbackNotify_ == nullptr) {
TELEPHONY_LOGE("RilAdapter serviceCallbackNotify_ is null");
HdfSBufRecycle(dataSbuf);
return HDF_FAILURE;
}
// Distribute events.
int32_t ret = serviceCallbackNotify_->dispatcher->Dispatch(
serviceCallbackNotify_, HNOTI_CALL_STATE_UPDATED, dataSbuf, nullptr);
if (ret != HDF_SUCCESS) {
HdfSBufRecycle(dataSbuf);
return HDF_FAILURE;
}
HdfSBufRecycle(dataSbuf);
return HDF_SUCCESS;
}
```
### Debugging and Verification<a name="section16999174401516"></a>
1. Use the [hdc\_std](en-us_topic_0000001080478129.md#section05992022154916) tool to connect to a debugging device. Then, run the following command to send the generated **libril\_vendor.z.so** library file to the **/system/lib/** directory of the device.
```
hdc_std file send libril_vendor.z.so /system/lib/
```
2. Reboot the debugging device.
```
hdc_std shell sync
hdc_std shell reboot
```
3. Run the **hdc\_std shell** command. Then, run the **./system/bin/ril\_adapter\_test** command, type **1**, and enter the phone number as prompted to test the call function.
```
hdc_std shell
# ./system/bin/ril_adapter_test
----> Test Enter --------->Call---------------------
1----> RilUnitTest::OnRequestCallDialTest
2----> RilUnitTest:: OnRequestCallHangupTest
3----> RilUnitTest:: OnRequestCallAnswerTest
4----> RilUnitTest::OnRequestCallGetCurrentCallsStatusTest
5----> RilUnitTest::OnRequestRefusedCallTest
1
```
4. Open another terminal window, and run the **hdc\_std shell hilog** command. Then, view the log to check whether **OnNotifyOps\(\)** is successfully executed. The following debug log is for reference:
```
01-01 00:08:01.334 546 551 D 02b01/TelRilTest: [DialResponse-(tel_ril_call.cpp:280)] DialResponse --> radioResponseInfo->serial:2, radioResponseInfo->error:0
01-01 00:08:01.334 546 557 D 02b01/TelRilTest: [ProcessEvent-(tel_ril_test.cpp:1262)] TelRilTest::DemoHandler::ProcessEvent --> eventId:101
01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur :
01-01 00:08:01.334 143 512 D 02b01/Rilvendor: ^ORIG:1,0
01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^ORIG:1,0
01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^ORIG:1,0
01-01 00:08:01.334 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^ORIG:1,0]:(null)
01-01 00:08:01.335 143 512 W 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:167)] enter to is unrecognized command: ^ORIG:1,0
01-01 00:08:01.335 143 512 D 02b01/Rilvendor: [ProcessLastResponse-(channel.c:37)] last data more than one line , FindEndOfLine g_bufferCur:
01-01 00:08:01.335 143 512 E 02b01/Rilvendor: [ProcessLastResponse-(channel.c:39)] g_bufferCur endLine is null
01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:93)] g_bufferCur :
01-01 00:08:01.336 143 512 D 02b01/Rilvendor: ^CCALLSTATE: 1,0,1
01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ReadResponse-(channel.c:108)] AT< ^CCALLSTATE: 1,0,1
01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [ProcessResponse-(at_support.c:137)] processLine line = ^CCALLSTATE: 1,0,1
01-01 00:08:01.336 143 512 D 02b01/Rilvendor: [OnNotifyOps-(vendor_report.c:126)] enter to [^CCALLSTATE: 1,0,1]:(null)
01-01 00:08:01.336 546 551 D 02b01/CoreService: [OnRemoteRequest-(tel_ril_manager.cpp:80)] RilManager OnRemoteRequest code:1001
01-01 00:08:01.336 546 551 D 02b01/CoreService: [NotifyObserver-(observer_handler.cpp:76)] handler->SendEvent:8
```
### Development Examples<a name="section33444350167"></a>
- **Outgoing Call**
The following figure shows the API calling for an outgoing call.
**Figure 1** Time sequence of API calling for an outgoing call<a name="fig494mcpsimp"></a>
![](figure/en-us_image_0000001171507146.png)
When an application initiates an outgoing call, RIL Adapter receives a call request, and the **hril** layer invokes the **ReqDial\(\)** function. In **ReqDial\(\)**, the data passed by the Telephony Service is encapsulated as an AT command and sent to the modem. After executing the dial command, the modem reports the execution result to RIL Adapter through **OnCallReport\(\)**.
```
// Callback function pointer of the call module
static const HRilCallReq g_callReqOps = {
.GetCallList = ReqGetCallList, // Obtain the call list.
.Dial = ReqDial, // Make a call.
.Hangup = ReqHangup, // Disconnect a call.
.Reject = ReqReject, // Reject a call.
.Answer = ReqAnswer, // Answer a call.
};
// Service request APIs
HRilOps g_hrilOps = {
.callOps = &g_callReqOps, // API for call service requests
.simOps = &g_simReqOps, // API for SIM card service requests
.smsOps = &g_smsReqOps, // API for SMS and MMS service requests
.networkOps = &g_networkReqOps, // API for cellular data service requests
.dataOps = &g_dataReqOps, // API for network search service requests
.modemOps = &g_modemReqOps, // API for modem service requests
};
// Implement the API for processing dial requests.
void ReqDial(ReqDataInfo *requestInfo, const void *data, size_t dataLen)
{
HRilDial *pDial = NULL;
char cmd[MAX_BUFF_SIZE] = {0};
const char *clir = NULL;
int ret;
int err = HRIL_ERR_SUCCESS;
struct ReportInfo reportInfo = {};
ResponseInfo *pResponse = NULL;
if (data == NULL) {
TELEPHONY_LOGE("data is null!!!");
err = HRIL_ERR_INVALID_PARAMETER;
reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
OnCallReport(reportInfo, NULL, 0);
return;
}
pDial = (HRilDial *)data;
switch (pDial->clir) {
case CALL_CLIR_INVOCATION:
clir = "I";
break; /* invocation */
case CALL_CLIR_SUPPRESSION:
clir = "i";
break; /* suppression */
case CALL_CLIR_SUBSCRIPTION_DEFUALT:
default:
clir = "";
break; /* subscription default */
}
(void)sprintf_s(cmd, MAX_BUFF_SIZE, "ATD%s%s;", pDial->address, clir);
ret = SendCommandLock(cmd, NULL, 0, &pResponse); // Send the AT command.
if (ret != 0) {
err = HRIL_ERR_CMD_SEND_FAILURE;
TELEPHONY_LOGE("ATD send failed");
} else {
if (pResponse != NULL && pResponse->success == 0) {
TELEPHONY_LOGE("ReqDial return ERROR");
err = HRIL_ERR_CMD_NO_CARRIER;
}
}
reportInfo = CreateReportInfo(requestInfo, err, HRIL_RESPONSE, 0);
OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
FreeResponseInfo(pResponse);
}
```
- **Incoming Call**
The following figure shows the API calling of an incoming call.
**Figure 2** Time sequence of API calling for an incoming call<a name="fig556mcpsimp"></a>
![](figure/en-us_image_0000001214727595.png)
The **g\_reader** thread cyclically reads the messages reported by the modem. When the modem receives an incoming call event, it actively reports the information about the incoming call.
The **g\_reader** thread calls **OnNotifyOps\(\)** to parse the reported information. If the parsed data reported by the modem starts with characters such as **+CRING** or **RING**, it indicates that an incoming call event exists. In this case, the event is reported to RIL Adapter through **OnCallReport\(reportInfo, NULL, 0\)**.
```
// Parse the data reported by the modem as events proactively reported by the corresponding module.
void OnNotifyOps(const char *s, const char *smsPdu)
{
int ret = 0;
struct ReportInfo reportInfo = {0};
reportInfo.error = HRIL_ERR_SUCCESS;
reportInfo.type = HRIL_NOTIFICATION;
if (GetRadioState() == HRIL_RADIO_POWER_STATE_UNAVAILABLE) {
return;
}
TELEPHONY_LOGD("enter to [%{public}s]:%{public}s", s, smsPdu);
// Determine the type of the proactively reported events based on the AT command.
if (ReportStrWith(s, "+CRING:") || ReportStrWith(s, "RING") || ReportStrWith(s, "IRING") ||
ReportStrWith(s, "NO CARRIER") || ReportStrWith(s, "+CCWA") || ReportStrWith(s, "^CCALLSTATE") ||
ReportStrWith(s, "^CEND") || ReportStrWith(s, "^CCWA")) {
reportInfo.notifyId = HNOTI_CALL_STATE_UPDATED;
OnCallReport(reportInfo, NULL, 0); // Invoke the callback function of the call service.
} else if (ReportStrWith(s, "+CMT:")) {
reportInfo.notifyId = HNOTI_SMS_NEW_SMS;
OnSmsReport(reportInfo, (void *)smsPdu, strlen(smsPdu));
}
// add your codes
......
}
```
## Integrating Modem Vendor Libraries<a name="section590mcpsimp"></a>
### Configuring Compilation Information<a name="section592mcpsimp"></a>
Compile the modem vendor library into a dynamic library by using **BUILD.gn**. Upon startup, RIL Adapter loads the dynamic library to the system in dlopen mode and then initializes the library. For details about how to implement vendor library initialization, see [Initializing a Modem Vendor Library](#section211mcpsimp). The following is an example of **BUILD.gn**:
```
import("//build/ohos.gni")
RIL_ADAPTER = "//base/telephony"
ohos_shared_library("ril_vendor") { // Modem vendor library
sources = [ // Source files to compile
"at_call.c",
"at_data.c",
"xxx.c",
]
include_dirs = [ // Header files
"$RIL_ADAPTER/ril_adapter/vendor/include",
"$RIL_ADAPTER/ril_adapter/interfaces/innerkits",
"include",
]
deps = [ // Internal dependencies
"//drivers/adapter/uhdf2/osal:libhdf_utils",
"//base/telephony/core_service/utils:libtelephony_common",
]
external_deps = [ "hilog:libhilog" ] // External dependencies
part_name = "ril_adapter" // Part name
subsystem_name = "telephony" // Subsystem name
}
```
### Debugging and Verification<a name="section620mcpsimp"></a>
1. Compile the code.
2. Check whether **libril\_vendor.z.so** exists in the **/out/ohos-arm-release/telephony/ril\_adapter** directory. If yes, the integration is successful. Otherwise, correct the error and perform debugging and verification again.
......@@ -7,7 +7,7 @@
The following figure shows the context structure of the Startup subsystem.
![](figure/startup-subsystem.png)
![](figure/The-following-figure-shows-the-context-structure-of-the-Startup-subsystem.png)
Upon completion of system power-on and kernel loading, system services and applications are started as follows:
......@@ -35,7 +35,7 @@ The Startup subsystem consists of the following modules:
- bootstrap module
This module provides entry identifiers for starting services and features. When samgr is started, the entry function identified by boostrap is called and system services are started.
This module provides entry identifiers for starting services and features. When samgr is started, the entry function identified by bootstrap is called and system services are started.
- syspara module
......
......@@ -260,7 +260,7 @@ The following table provides the sequence of loading system parameter value defi
</td>
<td class="cellrowborder" valign="top" width="30.183018301830185%" headers="mcps1.2.4.1.2 "><p id="p33425183117"><a name="p33425183117"></a><a name="p33425183117"></a>/vendor/etc/param/*.para</p>
</td>
<td class="cellrowborder" valign="top" width="53.15531553155315%" headers="mcps1.2.4.1.3 "><p id="p9342171861112"><a name="p9342171861112"></a><a name="p9342171861112"></a>The definition file containing system parameters in the <strong id="b974219911015"><a name="b974219911015"></a><a name="b974219911015"></a>vendor</strong> directory is loaded with the secondary priority. It can overwrite the definition file containing system parrameters in the <strong id="b1544125011115"><a name="b1544125011115"></a><a name="b1544125011115"></a>system</strong> directory.</p>
<td class="cellrowborder" valign="top" width="53.15531553155315%" headers="mcps1.2.4.1.3 "><p id="p9342171861112"><a name="p9342171861112"></a><a name="p9342171861112"></a>The definition file containing system parameters in the <strong id="b974219911015"><a name="b974219911015"></a><a name="b974219911015"></a>vendor</strong> directory is loaded with the secondary priority. It can overwrite the definition file containing system parameters in the <strong id="b1544125011115"><a name="b1544125011115"></a><a name="b1544125011115"></a>system</strong> directory.</p>
</td>
</tr>
<tr id="row1301784115"><td class="cellrowborder" valign="top" width="16.661666166616662%" headers="mcps1.2.4.1.1 "><p id="p234241851115"><a name="p234241851115"></a><a name="p234241851115"></a>System parameters in the <strong id="b0483162515513"><a name="b0483162515513"></a><a name="b0483162515513"></a>system</strong> directory</p>
......
# Subsystems
- [Telephony Service](telephony-service.md)
- [Telephony Service](telephony-service.md)
- [Development Guidelines](development-guidelines.md)
# Telephony Service<a name="EN-US_TOPIC_0000001164469232"></a>
- [Introduction](#section184mcpsimp)
- [Basic Concepts](#section187mcpsimp)
- [Working Principles](#section194mcpsimp)
- [Constraints](#section205mcpsimp)
## Introduction<a name="section184mcpsimp"></a>
This document provides development guidelines related to the telephony subsystem, including modem vendor library integration, initialization, service request responding, and modem event reporting. It is intended as a reference for developers of different modem chips, helping them efficiently develop telephony service-related functions.
## Basic Concepts<a name="section187mcpsimp"></a>
- Telephony Service: core service layer of the telephony subsystem. Its main functions are as follows:
- Initializes the RIL Manager module, SIM card module, and network search modules.
- Provides access to the RIL Adapter service, and implements communication with RIL Adapter by registering the callback service.
- Implements communication between modules, such as the call module and SMS module, by subscribing to callbacks.
- RIL Adapter: RIL adaptation layer of the Telephony subsystem. This layer provides functions such as vendor library loading and service API implementation. It shields the differences of modems supplied by different vendors to provide a unified API for the telephony service layer. It communicates with the telephony service layer by registering the Hardware Driver Foundation \(HDF\) service.
- HDF: Hardware Driver Foundation, which allows for unified access from peripheral devices and provides a framework for driver development and management.
- hdc\_std: OpenHarmony Device Connector, a command line tool provided by OpenHarmony for developers to debug device connectivity.
## Working Principles<a name="section194mcpsimp"></a>
**Figure 1** RIL Adapter architecture<a name="fig196mcpsimp"></a>
![](figure/en-us_image_0000001210683929.png)
As shown in the preceding figure, RIL Adapter is logically divided into three layers: **hril\_hdf**, **hril**, and **vendorlib**.
- **hril\_hdf**: unique entry of RIL Adapter. The main function of this layer is to load modem vendor library files. Wherein, **modem\_adapter** enables a single firmware to adapt to different modems.
Specifically, **hril\_hdf** obtains the modem type from the kernel and then loads the target modem vendor library based on the modem type.
- **hril**: OpenHarmony Radio Interface Layer, which provides APIs for communication between the **vendorlib** and various Telephony Service modules, including the SIM card, network search, cellular call, cellular data, and SMS/MMS modules.
- **vendorlib**: Modem vendor library file. Different modem vendor libraries are developed based on standard APIs or service request IDs provided by RIL Adapter. \(**vendorlib** is provided by modem vendors.\)
After **hril\_hdf** is executed, **vendorlib** is dynamically loaded so that it can obtain the pointers to the response processing and event reporting functions from **hril\_hdf**. After this process is complete, **hril\_hdf** can communicate with a modem through **vendorlib**.
## Constraints<a name="section205mcpsimp"></a>
**Specifications**
At least one modem must be supported by a device vendor. If no modem is supported, **vendorlib** APIs do not need to be implemented.
......@@ -49,6 +49,7 @@ This project stores OpenHarmony documentation, including the quick start guide,
- **porting**:
- [Standard System SoC Porting Guide](device-dev/porting/standard-system-porting-guide.md)
- [A Method for Rapidly Porting the OpenHarmony Linux Kernel ](device-dev/porting/porting-linux-kernel-overview.md)
- **bundles**:
- [HPM Bundle Development Specifications](device-dev/bundles/bundles-standard-rules.md)
......
......@@ -101,7 +101,7 @@ OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力,
## 验证<a name="section1949121910344"></a>
编译过程请参考《[Hi3861快速入门-源码编译](../quick-start/quickstart-lite-steps-hi3861-connection.md#section191121332125319)》,烧录过程请参考《[Hi3861快速入门-镜像烧录](../quick-start/quickstart-lite-steps-hi3861-connection.md#section19458165166)》。
编译过程请参考《[Hi3861快速入门-源码编译](../quick-start/quickstart-lite-steps-hi3861-connection.md#section191121332125319)》,烧录过程请参考《[Hi3861快速入门-镜像烧录](../quick-start/quickstart-lite-steps-hi3861-connection.md#section3288165814218)》。
完成以上两步后,按下RST键复位模组,可发现LED在周期性闪烁,与预期相符,验证完毕。
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册