未验证 提交 c3b9e204 编写于 作者: O openharmony_ci 提交者: Gitee

!3249 同步英文到3.1release分支【不需要翻译】

Merge pull request !3249 from duangavin123/OpenHarmony-3.1-Release
...@@ -40,7 +40,7 @@ In addition, OpenHarmony provides a series of optional system components that ca ...@@ -40,7 +40,7 @@ In addition, OpenHarmony provides a series of optional system components that ca
| Basic&nbsp;capabilities | Using&nbsp;basic&nbsp;capabilities&nbsp;of<br/>&nbsp;OpenHarmony | -&nbsp;[Kernel&nbsp;for&nbsp;Mini&nbsp;Systems](kernel/kernel-mini-overview.md)<br/>-&nbsp;[Kernel&nbsp;for&nbsp;Small&nbsp;Systems](kernel/kernel-small-overview.md)<br/>-&nbsp;[Drivers](driver/driver-hdf-overview.md)<br/>-&nbsp;[Subsystems](subsystems/subsys-build-mini-lite.md)<br/>-&nbsp;[Security&nbsp;Guidelines](security/security-guidelines-overall.md)<br/>-&nbsp;[Privacy&nbsp;Protection](security/security-privacy-protection.md) | | Basic&nbsp;capabilities | Using&nbsp;basic&nbsp;capabilities&nbsp;of<br/>&nbsp;OpenHarmony | -&nbsp;[Kernel&nbsp;for&nbsp;Mini&nbsp;Systems](kernel/kernel-mini-overview.md)<br/>-&nbsp;[Kernel&nbsp;for&nbsp;Small&nbsp;Systems](kernel/kernel-small-overview.md)<br/>-&nbsp;[Drivers](driver/driver-hdf-overview.md)<br/>-&nbsp;[Subsystems](subsystems/subsys-build-mini-lite.md)<br/>-&nbsp;[Security&nbsp;Guidelines](security/security-guidelines-overall.md)<br/>-&nbsp;[Privacy&nbsp;Protection](security/security-privacy-protection.md) |
| Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices&nbsp;based<br/>&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[WLAN-connected&nbsp;Products](guide/device-wlan-led-control.md)<br/>-&nbsp;[Cameras&nbsp;Without&nbsp;a&nbsp;Screen](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[Cameras&nbsp;with&nbsp;a&nbsp;Screen](guide/device-camera-control-overview.md) | | Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices&nbsp;based<br/>&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[WLAN-connected&nbsp;Products](guide/device-wlan-led-control.md)<br/>-&nbsp;[Cameras&nbsp;Without&nbsp;a&nbsp;Screen](guide/device-iotcamera-control-overview.md)<br/>-&nbsp;[Cameras&nbsp;with&nbsp;a&nbsp;Screen](guide/device-camera-control-overview.md) |
| Porting&nbsp;and&nbsp;adaptation | -&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the&nbsp;<br/>OpenHarmony&nbsp;to&nbsp;an&nbsp;SoC<br/>-&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a<br/>&nbsp;third-party&nbsp;library | -&nbsp;[Mini&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/oem_transplant_chip_prepare_knows.md)<br/>-&nbsp;[Small&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[Third-Party&nbsp;Library&nbsp;Porting&nbsp;Guide&nbsp;for&nbsp;Mini&nbsp;and&nbsp;Small&nbsp;Systems](porting/porting-thirdparty-overview.md) | | Porting&nbsp;and&nbsp;adaptation | -&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the&nbsp;<br/>OpenHarmony&nbsp;to&nbsp;an&nbsp;SoC<br/>-&nbsp;Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a<br/>&nbsp;third-party&nbsp;library | -&nbsp;[Mini&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/oem_transplant_chip_prepare_knows.md)<br/>-&nbsp;[Small&nbsp;System&nbsp;SoC&nbsp;Porting&nbsp;Guide](porting/porting-smallchip-prepare-needs.md)<br/>-&nbsp;[Third-Party&nbsp;Library&nbsp;Porting&nbsp;Guide&nbsp;for&nbsp;Mini&nbsp;and&nbsp;Small&nbsp;Systems](porting/porting-thirdparty-overview.md) |
| Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](bundles/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](bundles/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](bundles/hpm-part-reference.md) | | Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](hpm-part/hpm-part-reference.md) |
| Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | [FAQs](faqs/faqs-overview.md) | | Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | [FAQs](faqs/faqs-overview.md) |
...@@ -54,6 +54,6 @@ In addition, OpenHarmony provides a series of optional system components that ca ...@@ -54,6 +54,6 @@ In addition, OpenHarmony provides a series of optional system components that ca
| Basic&nbsp;capabilities | Using&nbsp;basic&nbsp;capabilities&nbsp;of&nbsp;OpenHarmony | -&nbsp;[Kernel&nbsp;for&nbsp;Standard&nbsp;Systems](kernel/kernel-standard-overview.md)<br/>-&nbsp;[Drivers](driver/driver-hdf-overview.md)<br/>-&nbsp;[Subsystems](subsystems/subsys-build-standard-large.md)<br/>-&nbsp;[Security&nbsp;Guidelines](security/security-guidelines-overall.md)<br/>-&nbsp;[Privacy&nbsp;Protection](security/security-privacy-protection.md) | | Basic&nbsp;capabilities | Using&nbsp;basic&nbsp;capabilities&nbsp;of&nbsp;OpenHarmony | -&nbsp;[Kernel&nbsp;for&nbsp;Standard&nbsp;Systems](kernel/kernel-standard-overview.md)<br/>-&nbsp;[Drivers](driver/driver-hdf-overview.md)<br/>-&nbsp;[Subsystems](subsystems/subsys-build-standard-large.md)<br/>-&nbsp;[Security&nbsp;Guidelines](security/security-guidelines-overall.md)<br/>-&nbsp;[Privacy&nbsp;Protection](security/security-privacy-protection.md) |
| Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices<br/>&nbsp;based&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[Development&nbsp;Guidelines&nbsp;on&nbsp;Clock&nbsp;Apps](guide/device-clock-guide.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Platform&nbsp;Drivers](guide/device-driver-demo.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Peripheral&nbsp;Drivers](guide/device-outerdriver-demo.md) | | Advanced&nbsp;development | Developing&nbsp;smart&nbsp;devices<br/>&nbsp;based&nbsp;on&nbsp;system&nbsp;capabilities | -&nbsp;[Development&nbsp;Guidelines&nbsp;on&nbsp;Clock&nbsp;Apps](guide/device-clock-guide.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Platform&nbsp;Drivers](guide/device-driver-demo.md)<br/>-&nbsp;[Development&nbsp;Example&nbsp;for&nbsp;Peripheral&nbsp;Drivers](guide/device-outerdriver-demo.md) |
| Porting&nbsp;and&nbsp;adaptation | Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a&nbsp;third-party&nbsp;library | -&nbsp;[Standard&nbsp;System&nbsp;Porting&nbsp;Guide](porting/standard-system-porting-guide.md)<br/>-&nbsp;[A&nbsp;Method&nbsp;for&nbsp;Rapidly&nbsp;Porting&nbsp;the&nbsp;OpenHarmony&nbsp;Linux&nbsp;Kernel](porting/porting-linux-kernel.md) | | Porting&nbsp;and&nbsp;adaptation | Porting&nbsp;and&nbsp;adapting&nbsp;the<br/>&nbsp;OpenHarmony&nbsp;to&nbsp;a&nbsp;third-party&nbsp;library | -&nbsp;[Standard&nbsp;System&nbsp;Porting&nbsp;Guide](porting/standard-system-porting-guide.md)<br/>-&nbsp;[A&nbsp;Method&nbsp;for&nbsp;Rapidly&nbsp;Porting&nbsp;the&nbsp;OpenHarmony&nbsp;Linux&nbsp;Kernel](porting/porting-linux-kernel.md) |
| Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](bundles/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](bundles/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](bundles/hpm-part-reference.md) | | Contributing&nbsp;components | Contributing&nbsp;components<br/>&nbsp;to&nbsp;OpenHarmony | -&nbsp;[HPM Part Overview](hpm-part/hpm-part-about.md)<br/>-&nbsp;[HPM Part Development](hpm-part/hpm-part-development.md)<br/>-&nbsp;[HPM Part Reference](hpm-part/hpm-part-reference.md) |
| Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | [FAQs](faqs/faqs-overview.md) | Reference | Referring&nbsp;to&nbsp;development&nbsp;specifications | [FAQs](faqs/faqs-overview.md)
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
- [HDF Development Example](driver-hdf-sample.md) - [HDF Development Example](driver-hdf-sample.md)
- [Platform Driver Development](driver-develop.md) - [Platform Driver Development](driver-develop.md)
- [ADC](driver-platform-adc-develop.md) - [ADC](driver-platform-adc-develop.md)
- [DAC](driver-platform-dac-develop.md)
- [GPIO](driver-platform-gpio-develop.md) - [GPIO](driver-platform-gpio-develop.md)
- [HDMI](driver-platform-hdmi-develop.md) - [HDMI](driver-platform-hdmi-develop.md)
- [I2C](driver-platform-i2c-develop.md) - [I2C](driver-platform-i2c-develop.md)
...@@ -26,12 +27,14 @@ ...@@ -26,12 +27,14 @@
- [Watchdog](driver-platform-watchdog-develop.md) - [Watchdog](driver-platform-watchdog-develop.md)
- [Platform Driver Usage](driver-platform.md) - [Platform Driver Usage](driver-platform.md)
- [ADC](driver-platform-adc-des.md) - [ADC](driver-platform-adc-des.md)
- [DAC](driver-platform-dac-des.md)
- [GPIO](driver-platform-gpio-des.md) - [GPIO](driver-platform-gpio-des.md)
- [HDMI](driver-platform-hdmi-des.md) - [HDMI](driver-platform-hdmi-des.md)
- [I2C](driver-platform-i2c-des.md) - [I2C](driver-platform-i2c-des.md)
- [I3C](driver-platform-i3c-des.md) - [I3C](driver-platform-i3c-des.md)
- [MIPI CSI](driver-platform-mipicsi-des.md) - [MIPI CSI](driver-platform-mipicsi-des.md)
- [MIPI DSI](driver-platform-mipidsi-des.md) - [MIPI DSI](driver-platform-mipidsi-des.md)
- [Pin](driver-platform-pin-des.md)
- [PWM](driver-platform-pwm-des.md) - [PWM](driver-platform-pwm-des.md)
- [Regulator](driver-platform-regulator-des.md) - [Regulator](driver-platform-regulator-des.md)
- [RTC](driver-platform-rtc-des.md) - [RTC](driver-platform-rtc-des.md)
...@@ -46,4 +49,6 @@ ...@@ -46,4 +49,6 @@
- [WLAN](driver-peripherals-external-des.md) - [WLAN](driver-peripherals-external-des.md)
- [Audio](driver-peripherals-audio-des.md) - [Audio](driver-peripherals-audio-des.md)
- [USB](driver-peripherals-usb-des.md) - [USB](driver-peripherals-usb-des.md)
- [Camera](driver-peripherals-camera-des.md) - [Camera](driver-peripherals-camera-des.md)
\ No newline at end of file - [Vibrator](driver-peripherals-vibrator-des.md)
- [Light](driver-peripherals-light-des.md)
\ No newline at end of file
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
- **[ADC](driver-platform-adc-develop.md)** - **[ADC](driver-platform-adc-develop.md)**
- **[DAC](driver-platform-dac-develop.md)**
- **[GPIO](driver-platform-gpio-develop.md)** - **[GPIO](driver-platform-gpio-develop.md)**
- **[HDMI](driver-platform-hdmi-develop.md)** - **[HDMI](driver-platform-hdmi-develop.md)**
......
# Driver Development<a name="EN-US_TOPIC_0000001051930361"></a> # Driver Development
## Driver Model<a name="section157425168112"></a>
## Driver Model
The HDF is designed based on the component-based driver model. This model allows refined driver management and normalizes driver development and deployment. 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.
The Hardware Driver Foundation (HDF) is designed based on the component-based driver model. This model allows refined driver management and standardize driver development and deployment. 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. The figure below shows the HDF driver model.
**Figure 1** HDF driver model<a name="fig3580184214210"></a>
![](figures/hdf-driver-model.png "hdf-driver-model") **Figure 1** HDF driver model
## How to Develop<a name="section1969312275533"></a> ![](figures/hdf-driver-model.png)
Driver development based on the HDF involves driver implementation and driver configuration. The development procedure is as follows:
## How to Development
1. <a name="li35182436435"></a>Implement a driver.
The HDF-based driver development involves driver implementation and driver configuration. The development procedure is as follows:
To implement a driver, compile driver service code and register a driver entry.
1. Implement a driver.
- Driver service code To implement a driver, compile driver service code and register a driver entry.
``` - Driver service code
#include "hdf_device_desc.h" // Header file that describes the APIs provided by the HDF to the driver.
#include "hdf_log.h" // Header file that describes the log APIs provided by the HDF. ```
#include "hdf_device_desc.h" // Header file that describes the APIs provided by the HDF to the driver.
#define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used. #include "hdf_log.h" // Header file that describes the log APIs provided by the HDF.
// The driver service interface must be bound to the HDF for you to use the service capability. #define HDF_LOG_TAG "sample_driver" // Tag contained in logs. If no tag is not specified, the default HDF_TAG is used.
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{ // Service capabilities provided by the driver. Bind the service APIs to the HDF.
HDF_LOGD("Sample driver bind success"); int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
return 0; {
} HDF_LOGD("Sample driver bind success");
return 0;
// Initialize the driver service. }
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{ // Initialize the driver service.
HDF_LOGD("Sample driver Init success"); int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
return 0; {
} HDF_LOGD("Sample driver Init success");
return 0;
// Release the driver resources. }
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{ // Release the driver resources.
HDF_LOGD("Sample driver release success"); void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
return; {
} HDF_LOGD("Sample driver release success");
``` return;
}
- Registering the driver entry with the HDF ```
- Registering the driver entry with the HDF
```
// Define the object of the driver entry. The object must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h). ```
struct HdfDriverEntry g_sampleDriverEntry = { // Define a driver entry object. It must be a global variable of the HdfDriverEntry type (defined in hdf_device_desc.h).
.moduleVersion = 1, struct HdfDriverEntry g_sampleDriverEntry = {
.moduleName = "sample_driver", .moduleVersion = 1,
.Bind = HdfSampleDriverBind, .moduleName = "sample_driver",
.Init = HdfSampleDriverInit, .Bind = HdfSampleDriverBind,
.Release = HdfSampleDriverRelease, .Init = HdfSampleDriverInit,
}; .Release = HdfSampleDriverRelease,
};
// Call HDF_INIT to register the driver entry with the HDF framework. When loading the driver, call the Bind function and then the Init function. If the Init function fails to be called, the HDF will call Release to release the driver resource and exit.
HDF_INIT(g_sampleDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function first and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release the driver resources and exit the driver model.
``` HDF_INIT(g_sampleDriverEntry);
```
2. Build the driver. 2. Build the driver.
- LiteOS - LiteOS
Modify **makefile** and **BUILD.gn**.
Modify **makefile** and **BUILD.gn**:
- makefile:
* makefile: Use the **makefile** template provided by the HDF to compile the driver code.
Use the **makefile** template provided by the HDF to compile the driver code.
```
``` include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory.
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk # Import the content predefined by the HDF. This operation is mandatory. MODULE_NAME := # File to be generated.
MODULE_NAME := # File to be generated. LOCAL_INCLUDE: = # Header file directory of the driver.
LOCAL_INCLUDE: = # Header file directory of the driver. LOCAL_SRCS : = # Source code file of the driver.
LOCAL_SRCS : = # Source code file of the driver. LOCAL_CFLAGS : = # Custom compilation options.
LOCAL_CFLAGS : = # Custom compilation options. include $(HDF_DRIVER) # Import the makefile template to complete the compilation.
include $(HDF_DRIVER) # Import the makefile template to complete the compilation. ```
```
Add the path of the generated file to **hdf_lite.mk** in the **drivers/adapter/khdf/liteos** directory to link the file to the kernel image. The following is an example:
Add the path of the generated file to **hdf_lite.mk** in the **drivers/adapter/khdf/liteos** directory to link the file to the kernel image. The following is an example:
``` ```
LITEOS_BASELIB += -lxxx # Static library generated by the link. LITEOS_BASELIB += -lxxx # Static library generated by the link.
LIB_SUBDIRS += # Directory in which the driver code makefile is located. LIB_SUBDIRS += # Directory in which the driver code makefile is located.
``` ```
* BUILD.gn: - **BUILD.gn**:
Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
Add **BUILD.gn**. The content of **BUILD.gn** is as follows:
``` ```
import("//build/lite/config/component/lite_component.gni") import("//build/lite/config/component/lite_component.gni")
import("//drivers/adapter/khdf/liteos/hdf.gni") import("//drivers/adapter/khdf/liteos/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF_xxx) module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
module_name = "xxx" module_name = "xxx"
hdf_driver(module_name) { hdf_driver(module_name) {
sources = [ sources = [
"xxx/xxx/xxx.c", # Source code file of the driver "xxx/xxx/xxx.c", # Source code file of the driver
] ]
public_configs = [ ":public" ] # Configuration applied to dependencies public_configs = [ ":public" ] # Configuration applied to dependencies
} }
config("public") {# Configuration of the dependencies config("public") {# Configuration of the dependencies
include_dirs = [ include_dirs = [
"xxx/xxx/xxx", # Directory of the dependency header file. "xxx/xxx/xxx", # Directory of the dependency header file.
] ]
} }
``` ```
Add the directory where the **BUILD.gn** file of the driver is located to **/drivers/adapter/khdf/liteos/BUILD.gn**. Add the directory where the **BUILD.gn** file of the driver is located to **/drivers/adapter/khdf/liteos/BUILD.gn**.
```
group("liteos") { ```
public_deps = [ ":$module_name" ] group("liteos") {
deps = [ public_deps = [ ":$module_name" ]
"xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos. deps = [
] "xxx/xxx", # Directory where the BUILD.gn of the driver is located. It is a relative path to /drivers/adapter/khdf/liteos.
} ]
``` }
```
- Linux - Linux
To define the driver control macro, add the **Kconfig** file to the driver directory **xxx** and add the path of the **Kconfig** file to **drivers/adapter/khdf/linux/Kconfig**.
To define the driver control macro, add the **Kconfig** file to the driver directory **xxx** and add the path of the **Kconfig** file to **drivers/adapter/khdf/linux/Kconfig**.
``` ```
source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked. source "drivers/hdf/khdf/xxx/Kconfig" # Kernel directory to which the HDF module is soft linked.
``` ```
Add the driver directory to **drivers/adapter/khdf/linux/Makefile**. Add the driver directory to **drivers/adapter/khdf/linux/Makefile**.
```
obj-$(CONFIG_DRIVERS_HDF) += xxx/ ```
``` obj-$(CONFIG_DRIVERS_HDF) += xxx/
```
Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
Add a **Makefile** to the driver directory **xxx** and add code compiling rules of the driver to the **Makefile** file.
```
obj-y += xxx.o
``` ```
obj-y += xxx.o
3. Configure the driver. ```
HDF Configuration Source (HCS) is the source code that describes the configuration of the HDF. For details about the HCS, see [Driver Configuration Management](driver-hdf-manage.md). 3. Configure the driver.
HDF Configuration Source (HCS) is the source code that describes the configuration of the HDF. For details about the HCS, see [Driver Configuration Management](../driver/driver-hdf-manage.md).
The driver configuration consists of the driver device description defined by the HDF and private driver configuration information.
The driver configuration consists of the driver device description defined by the HDF and the private driver configuration.
- (Mandatory) Driver device description
- (Mandatory) Driver device description
The information required for the HDF to load drivers comes from the driver device description defined by the HDF. Therefore, the device description must be added to the configuration file **device_info.hcs** defined by the HDF for drivers developed based on the HDF.The following is an example: The information required for the HDF to load drivers comes from the driver device description defined by the HDF. Therefore, the device description must be added to the configuration file **device_info.hcs** defined by the HDF for drivers developed based on the HDF. The following is an example:
```
root { ```
device_info { root {
match_attr = "hdf_manager"; device_info {
template host { // Host template. If the node (for example, sample_host) that inherits the template uses default values in the template, the values of the node fields can be omitted. match_attr = "hdf_manager";
hostName = ""; template host { // Host template. If the node (for example, sample_host) uses the default values in the template, the values of the node fields can be omitted.
priority = 100; hostName = "";
template device { priority = 100;
template deviceNode { uid = ""; // User ID (UID) of the user-mode process. By default, it is left empty, that is, set to the value defined for hostName, which indicates a common user.
policy = 0; gid = ""; // Group ID (GID) of the user-mode process. By default, it is left empty, that is, set to the value defined for hostName, which indicates a common user group.
priority = 100; caps = [""]]; // Linux capabilities of the user-mode process. It is left empty by default. Set this parameter based on service requirements.
preload = 0; template device {
permission = 0664; template deviceNode {
moduleName = ""; policy = 0;
serviceName = ""; priority = 100;
deviceMatchAttr = ""; preload = 0;
} permission = 0664;
} moduleName = "";
} serviceName = "";
sample_host :: host{ deviceMatchAttr = "";
hostName = "host0"; // Host name. The host node is used to store a certain type of drivers. }
priority = 100; // Host startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence is random. }
device_sample :: device { // Device node of sample }
device0 :: deviceNode { // DeviceNode of the sample driver sample_host :: host{
policy = 1; // Driver service release policy. For details, see section Driver Service Management. hostName = "host0"; // Host name. The host node is used to store a type of drivers.
priority = 100; // Driver startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the device loading sequence is random. priority = 100; // Host startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence is random.
preload = 0; // On-demand loading of the driver. For details, see "NOTE" at the end of this section. caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // Linux capabilities of the user-mode process.
permission = 0664; // Permission for the driver to create device nodes. device_sample :: device { // Sample device node.
moduleName = "sample_driver"; // Driver name. The value of this field must be the same as the value of moduleName in the driver entry structure. device0 :: deviceNode { // DeviceNode of the sample driver.
serviceName = "sample_service"; // Name of the service released by the driver. The name must be unique. policy = 1; // Driver service release policy. For details, see the Driver Service Management.
deviceMatchAttr = "sample_config"; // 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. priority = 100; // Driver startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the host loading sequence is random.
} preload = 0; // On-demand loading of the driver. For details, see "NOTE" at the end of this section.
} permission = 0664; // Permission for the driver to create a device node.
} moduleName = "sample_driver"; // Driver name. The value of this field must be the same as that of moduleName in the HdfDriverEntry structure.
} serviceName = "sample_service"; // Name of the service published by the driver. The service name must be unique.
} deviceMatchAttr = "sample_config"; // Keyword for matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
``` }
}
- \(Optional\) Private configuration information of the driver }
}
If the driver has private configurations, you can add a driver configuration file to fill in the default configuration information of the driver. When loading the driver, the HDF obtains the information and saves it in the **property** of **HdfDeviceObject**, and transfers it to the driver using **Bind** and **Init** \(see [1](#li35182436435)\). The following is an example of the driver configuration information: }
```
``` > ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**<br/>
root {
SampleDriverConfig { - **uid**, **gid**, and **caps** are startup configuration for user-mode drivers and do not need to be configured for kernel-mode drivers.
sample_version = 1; - According to the principle of least privilege for processes, **uid** and **gid** do not need to be configured for service modules. In the preceding example, **uid** and **gid** are left empty (granted with the common user rights) for sample_host.
sample_bus = "I2C_0"; - If you need to set **uid** and **gid** to **system** or **root** due to service requirements, contact security experts for review.
match_attr = "sample_config"; // The value of this field must be the same as that of deviceMatchAttr in device_info.hcs. - The process UID is configured in **base/startup/init_lite/services/etc/passwd**, and the process GID is configured in **base/startup/init_lite/services/etc/group**. For details, see [Adding a System Service User Group]( https://gitee.com/openharmony/startup_init_lite/wikis).
} - If CAP_DAC_OVERRIDE needs to be configured for a service module, set **caps = ["DAC_OVERRIDE"]** instead of **caps = ["CAP_DAC_OVERRIDE"]**.
}
```
After the configuration information is defined, you need to add the configuration file to the board-level configuration entry file **hdf.hcs**. \(You can use the DevEco to perform on-click configuration. For details, see the description about the driver development suite.\) The following is an example: - (Optional) Private configuration information of the driver
If the driver has private configuration, you can add a driver configuration file to set default driver configuration. When loading the driver, the HDF obtains and saves the corresponding configuration in **property** of **HdfDeviceObject**, and passes the configuration to the driver through **Bind()** and **Init()** (see step 1). The following is an example of the driver configuration:
```
#include "device_info/device_info.hcs"
#include "sample/sample_config.hcs" ```
``` root {
SampleDriverConfig {
sample_version = 1;
sample_bus = "I2C_0";
>![](../public_sys-resources/icon-note.gif) **NOTE:** match_attr = "sample_config"; // The value of this field must be the same as that of deviceMatchAttr in device_info.hcs.
>On-demand loading and sequential loading are supported. The detailed usage is as follows: }
>- On-demand loading }
> ``` ```
> typedef enum {
> DEVICE_PRELOAD_ENABLE = 0, After the configuration, add the configuration file to the board-level configuration entry file **hdf.hcs**. (You can use DevEco to perform on-click configuration. For details, see the description about the driver development suite.) The following is an example:
> DEVICE_PRELOAD_ENABLE_STEP2,
> DEVICE_PRELOAD_DISABLE,
> DEVICE_PRELOAD_INVALID ```
> } DevicePreload; #include "device_info/device_info.hcs"
> ``` #include "sample/sample_config.hcs"
> If the **preload** field in the configuration file is set to **0** (DEVICE\_PRELOAD\_ENABLE), the driver is loaded by default during the system boot process. If **preload** is set to **1** (DEVICE\_PRELOAD\_ENABLE\_STEP2), the driver is loaded after a quick start is complete if the system supports quick start. If the system does not support quick start, the value **1** has the same meaning as DEVICE\_PRELOAD\_ENABLE. If **preload** is set to **2** (DEVICE\_PRELOAD\_DISABLE), the driver is dynamically loaded instead of being loaded during the system boot process. When a user-mode process requests the driver service (for details, see [Driver Message Mechanism Management](driver-hdf-message-management.md)), the HDF attempts to dynamically load the driver if the driver service does not exist. ```
>- 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.
> ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> Drivers can be loaded on demand or in sequence.
>
> - On-demand loading
>
> ```
> typedef enum {
> DEVICE_PRELOAD_ENABLE = 0,
> DEVICE_PRELOAD_ENABLE_STEP2,
> DEVICE_PRELOAD_DISABLE,
> DEVICE_PRELOAD_INVALID
> } DevicePreload;
> ```
>
> If **preload** in the configuration file is set to **0** (**DEVICE_PRELOAD_ENABLE**), the driver is loaded by default during the system boot process.
>
> If **preload** is set to **1** (**DEVICE\_PRELOAD\_ENABLE\_STEP2**), the driver is loaded after a quick start is complete if the system supports quick start. If the system does not support quick start, the value **1** has the same meaning as **DEVICE\_PRELOAD\_ENABLE**.
>
> If **preload** is set to **2** (**DEVICE\_PRELOAD\_DISABLE**), the driver is dynamically loaded instead of being loaded during the system boot process. When a user-mode process requests the driver service (for details, see [Driver Message Mechanism Management](driver-hdf-message-management.md)), the HDF attempts to dynamically load the driver if the driver service does not exist.
>
> - Sequential loading (drivers must be loaded by default)
> In the configuration file, the **priority** field \(value range: 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.
# Audio # Audio
# Audio Driver Overview<a name="section1000"></a>
## Audio Driver Overview
A multimedia system is an indispensable part in Internet of Things (IoT) devices. Audio is an important module of the multimedia system, and building an audio driver model is particularly important in device development. A multimedia system is an indispensable part in Internet of Things (IoT) devices. Audio is an important module of the multimedia system, and building an audio driver model is particularly important in device development.
...@@ -8,9 +9,10 @@ This document describes the audio driver architecture and functional modules and ...@@ -8,9 +9,10 @@ This document describes the audio driver architecture and functional modules and
# Audio Driver Architecture<a name="section2000"></a> ## Audio Driver Architecture
The audio driver architecture is implemented based on the [HDF](https://device.harmonyos.com/en/docs/documentation/guide/driver-hdf-overview-0000001051715456). The audio driver architecture is as follows: The audio driver architecture is implemented based on the [HDF](https://device.harmonyos.com/en/docs/documentation/guide/driver-hdf-overview-0000001051715456). The audio driver architecture is as follows:
![](figures/Audio_architecture.png) ![](figures/Audio_architecture.png)
The driver architecture consists of the following: The driver architecture consists of the following:
...@@ -21,14 +23,14 @@ The driver architecture consists of the following: ...@@ -21,14 +23,14 @@ The driver architecture consists of the following:
- Audio Stream Dispatch: dispatches the data from the Audio Interface Lib to the driver layer. - Audio Stream Dispatch: dispatches the data from the Audio Interface Lib to the driver layer.
- Card Manager: manages multiple audio adapters. Each audio adapter consists of the digital audio interface (DAI), platform, codec, accessory, DSP, and Smart Audio Power Manager (SAPM) modules. - Card Manager: manages multiple audio adapters. Each audio adapter consists of the digital audio interface (DAI), platform, codec, accessory, DSP, and Smart Audio Power Manager (SAPM) modules.
- Platform Drivers: implement driver adaptation. - Platform Drivers: driver adaptation layer.
- SAPM: optimizes the power consumption policy of the ADM. - SAPM: optimizes the power consumption policy of the ADM.
# Audio Driver Development<a name="section3000"></a> ## Audio Driver Development
The following uses the Hi3516D V300 as an example to describe how to develop drivers based on the audio driver architecture. The following uses the Hi3516D V300 as an example to describe how to develop drivers based on the audio driver architecture.
## Audio ADM Architecture<a name="section3100"></a> ### Audio ADM Architecture
The audio driver provides the **hdf_audio_render**, **hdf_audio_capture**, and **hdf_audio_control** services for the HDI layer. The driver service nodes in the **dev** directory of the development board are as follows: The audio driver provides the **hdf_audio_render**, **hdf_audio_capture**, and **hdf_audio_control** services for the HDI layer. The driver service nodes in the **dev** directory of the development board are as follows:
```c ```c
...@@ -43,10 +45,10 @@ crw-rw---- 1 system system 248, 7 1970-01-01 00:00 hdf_audio_render // Aud ...@@ -43,10 +45,10 @@ crw-rw---- 1 system system 248, 7 1970-01-01 00:00 hdf_audio_render // Aud
The audio adapters have the following driver services: The audio adapters have the following driver services:
hdf\_audio\_codec\_dev0 hdf\_audio\_codec\_dev0
- **dma\_service\_0**: direct memory access (DMA) service - **dma\_service\_0**: direct memory access (DMA) service
- **dai_service**: CPU DAI service - **dai_service**: CPU DAI service
- **codec\_service\_0**: codec service (built-in codec) - **codec\_service\_0**: codec service (built-in codec)
- **dsp\_service\_0**: DSP service (optional) - **dsp\_service\_0**: DSP service (optional)
hdf\_audio\_codec\_dev1 hdf\_audio\_codec\_dev1
- **dma\_service\_0**: DMA service - **dma\_service\_0**: DMA service
...@@ -54,7 +56,7 @@ hdf\_audio\_codec\_dev1 ...@@ -54,7 +56,7 @@ hdf\_audio\_codec\_dev1
- **codec\_service\_1**: accessory service (SmartPA) - **codec\_service\_1**: accessory service (SmartPA)
- **dsp\_service\_0**: DSP service (optional) - **dsp\_service\_0**: DSP service (optional)
### Startup Process<a name="section3111"></a> #### Startup Process
![](figures/ADM_startup_flowchart.png) ![](figures/ADM_startup_flowchart.png)
...@@ -68,8 +70,10 @@ hdf\_audio\_codec\_dev1 ...@@ -68,8 +70,10 @@ hdf\_audio\_codec\_dev1
5. The initialized audio devices are added to the cardManager linked list. 5. The initialized audio devices are added to the cardManager linked list.
### Playback Process<a name="section3112"></a> #### Playback Process
![=](figures/ADM_playback_flowchart.png) ![=](figures/ADM_playback_flowchart.png)
1. The Audio Interface Lib sends the **Render Open** instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the API of each module to deliver the instruction. 1. The Audio Interface Lib sends the **Render Open** instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the API of each module to deliver the instruction.
2. The Audio Interface Lib sends a path select instruction to the Control Dispatch service. The Control Dispatch service calls the DAI API to set the path. 2. The Audio Interface Lib sends a path select instruction to the Control Dispatch service. The Control Dispatch service calls the DAI API to set the path.
...@@ -84,52 +88,52 @@ hdf\_audio\_codec\_dev1 ...@@ -84,52 +88,52 @@ hdf\_audio\_codec\_dev1
7. The Audio Interface Lib sends the **Render Close** instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the **Platform AudioRenderClose** API to release resources. 7. The Audio Interface Lib sends the **Render Close** instruction to the Audio Stream Dispatch service. The Audio Stream Dispatch service calls the **Platform AudioRenderClose** API to release resources.
### Control Process<a name="section3113"></a> #### Control Process
![](figures/ADM_control_flowchart.png) ![](figures/ADM_control_flowchart.png)
1. When the volume needs to be adjusted, the Audio Interface Lib sends an instruction for obtaining the volume range to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **get()** of the codec module to obtain the volume range. 1. When the volume needs to be adjusted, the Audio Interface Lib sends an instruction for obtaining the volume range to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **get()** of the codec module to obtain the volume range.
2. The Audio Interface Lib sends an instruction for setting the volume to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **Set()** of the codec module to set the volume. 2. The Audio Interface Lib sends an instruction for setting the volume to the Control Dispatch service. The Control Dispatch service parses the instruction and calls **Set()** of the codec module to set the volume.
## Audio Driver Development Procedure<a name="section3200"></a> ### Audio Driver Development Procedure
### Development on an Adapted Platform<a name="section3221"></a> #### Development on an Adapted Platform
The following figure shows the process for developing the codec or accessory (SmartPA) driver on a chip platform (Hi3516D V300) to which the ADM has adapted. The following figure shows the process for developing the codec or accessory (SmartPA) driver on a chip platform (Hi3516D V300) to which the ADM has adapted.
![](figures/development_flowchart_1.png) ![](figures/audio_development_flowchart_1.png)
1. Add register information to the private HDF configuration source (HCS) of the codec or SmartPA based on the chip description. - Add register information to the private HDF configuration source (HCS) of the codec or SmartPA based on the chip description.
If the workflow of the newly added codec or SmartPA is the same as that of the existing codec or SmartPA, you do not need to implement the operation function set or configure the compilation file for the newly added codec or SmartPA. - If the workflow of the newly added codec or SmartPA is the same as that of the existing codec or SmartPA, you do not need to implement the operation function set or configure the compilation file for the newly added codec or SmartPA.
2. Perform build, debugging, and testing. - Perform build, debugging, and testing.
### Development on a New Platform<a name="section3222"></a> #### Development on a New Platform
The following figure shows the driver development process if the ADM has not adapted to the platform. The following figure shows the driver development process if the ADM has not adapted to the platform.
![](figures/development_flowchart_2.png) ![](figures/audio_development_flowchart_2.png)
The codec (optional), DAI, DMA, DSP (optional), and SmartPA (optional) modules of the audio adapter need to be adapted to the new platform. The codec (optional), DAI, DMA, DSP (optional), and SmartPA (optional) modules of the audio adapter need to be adapted to the new platform.
1. Add register information of each module driver to the private configuration file of the respective module according to the chip description. - Add register information of each module driver to the private configuration file of the respective module according to the chip description.
2. Implement the operation function set of each module. - Implement the operation function set of each module.
3. Modify the compilation file of the audio module. - Modify the compilation file of the audio module.
4. Perform build, debugging, and testing. - Perform build, debugging, and testing.
# Audio Driver Development Examples<a name="section4000"></a> ## Audio Driver Development Examples
Code path: **drivers/peripheral/audio** Code path: **drivers/peripheral/audio**
The following uses Hi3516D V300 as an example to describe how to develop the audio codec driver, accessory driver, DAI driver, and platform driver. The following uses Hi3516D V300 as an example to describe how to develop the audio codec driver, accessory driver, DAI driver, and platform driver.
## Codec Driver Development Example<a name="section4100"></a> ### Codec Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/codec** Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/codec**
The major steps for developing the codec driver are as follows: The major steps for developing the codec driver are as follows:
...@@ -138,7 +142,7 @@ The major steps for developing the codec driver are as follows: ...@@ -138,7 +142,7 @@ The major steps for developing the codec driver are as follows:
3. Register and bind the codec instance to the HDF. 3. Register and bind the codec instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
### Filling in Codec Data Structures<a name="section4111"></a> #### Filling in Codec Data Structures
Fill in the following data structures for the codec module: Fill in the following data structures for the codec module:
...@@ -166,9 +170,9 @@ struct DaiData g_codecDaiData = { ...@@ -166,9 +170,9 @@ struct DaiData g_codecDaiData = {
}; };
``` ```
### Initializing the Codec Device and Codec DAI Device<a name="section4112"></a> #### Initializing codecDevice and codecDai
**CODECDeviceInit** sets audio input/audio output (AIAO), initializes registers, inserts **g_audioControls** into the controller linked list, initializes the power management, and selects a path. **CODECDeviceInit** sets audio input/audio output (AIAO), initializes registers, inserts **g_audioControls** into the control linked list, initializes the power management, and selects a path.
```c ```c
int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
...@@ -183,7 +187,7 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) ...@@ -183,7 +187,7 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
/* Initialize the codec registers of the Hi3516 platform. */ /* Initialize the codec registers of the Hi3516 platform. */
CodecRegDefaultInit(codec->devData->regCfgGroup); CodecRegDefaultInit(codec->devData->regCfgGroup);
... ...
/* Insert g_audioControls of the Hi3516 platform to the controller linked list. */ /* Insert g_audioControls of the Hi3516 platform to the controller linked list.*/
AudioAddControls(audioCard, codec->devData->controls, codec->devData->numControls); AudioAddControls(audioCard, codec->devData->controls, codec->devData->numControls);
... ...
/* Load the codec of the Hi3516 platform to the SAPM. */ /* Load the codec of the Hi3516 platform to the SAPM. */
...@@ -214,7 +218,7 @@ int32_t CodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *devic ...@@ -214,7 +218,7 @@ int32_t CodecDaiDeviceInit(struct AudioCard *card, const struct DaiDevice *devic
} }
``` ```
### Implementing the Codec Operation Function Set<a name="section4113"></a> #### Implementing the Codec Operation Function Set
The codec module is encapsulated with the **read()** and **write()** functions of the read and write registers at the operating system abstraction layer (OSAL). The codec module is encapsulated with the **read()** and **write()** functions of the read and write registers at the operating system abstraction layer (OSAL).
...@@ -267,7 +271,7 @@ int32_t CodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwPa ...@@ -267,7 +271,7 @@ int32_t CodecDaiHwParams(const struct AudioCard *card, const struct AudioPcmHwPa
} }
``` ```
### Registering and Binding Codec to HDF<a name="section4114"></a> #### Registering and Binding Codec to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md). This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md).
...@@ -299,7 +303,7 @@ static int32_t CodecDriverBind(struct HdfDeviceObject *device) ...@@ -299,7 +303,7 @@ static int32_t CodecDriverBind(struct HdfDeviceObject *device)
} }
``` ```
**CodecDriverInit** obtains the codec service name and private register configuration, and inserts them into the linked list by using **AudioRegisterCodec**. **CodecDriverInit** obtains the **codecService** name and private register configuration, and inserts them into the linked list by using **AudioRegisterCodec**.
```c ```c
static int32_t CodecDriverInit(struct HdfDeviceObject *device) static int32_t CodecDriverInit(struct HdfDeviceObject *device)
...@@ -325,7 +329,7 @@ static void CodecDriverRelease(struct HdfDeviceObject *device) ...@@ -325,7 +329,7 @@ static void CodecDriverRelease(struct HdfDeviceObject *device)
} }
``` ```
### Configuring HCS<a name="section4115"></a> #### Configuring HCS<a name="section4115"></a>
Configure the driver node, loading sequence, and service name in the .hcs file. For details about the HCS syntax, see [Driver Configuration Management](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf-manage.md) in the HDF. Configure the driver node, loading sequence, and service name in the .hcs file. For details about the HCS syntax, see [Driver Configuration Management](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf-manage.md) in the HDF.
...@@ -339,7 +343,7 @@ Path of the small-system configuration file: ...@@ -339,7 +343,7 @@ Path of the small-system configuration file:
**Configuring Codec Device Information in device_info.hcs** **Configuring Codec Device Information in device_info.hcs**
Add codec node configuration. Modify **moduleName** in the configuration file. The value must be the same as **moduleName** in the **HdfDriverEntry** structure. Generally, the value should present the hardware platform, for example, **moduleName = "CODEC_HI3516"**. Add codec node configuration. Modify **moduleName** in the configuration file. The value must be the same as **moduleName** in the **HdfDriverEntry** structure. Generally, the value should present the hardware platform. For example, moduleName = "CODEC_HI3516".
The code snippet is as follows: The code snippet is as follows:
...@@ -366,7 +370,7 @@ The code snippet is as follows: ...@@ -366,7 +370,7 @@ The code snippet is as follows:
```c ```c
root { root {
platfrom { platform {
... ...
controller_0x120c1001 :: card_controller { controller_0x120c1001 :: card_controller {
// Set the private data attribute name, which must be the same as deviceMatchAttr in device_info.hcs. // Set the private data attribute name, which must be the same as deviceMatchAttr in device_info.hcs.
...@@ -425,11 +429,11 @@ iface ...@@ -425,11 +429,11 @@ iface
6: AIAO device 6: AIAO device
``` ```
**ctrlParamsSeqConfig**: control functionality register configuration. The sequence of the configuration items is the same as that in **controlsConfig**, indicating the register configuration corresponding to a functionality. **ctrlParamsSeqConfig**: control function register configuration. The **item** sequence corresponds to the **item** sequence in **controlsConfig**, indicating the register configuration corresponding to a function.
```c ```c
root { root {
platfrom { platform {
template codec_controller { template codec_controller {
match_attr = ""; match_attr = "";
serviceName = ""; serviceName = "";
...@@ -496,7 +500,7 @@ iface ...@@ -496,7 +500,7 @@ iface
0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, //"Mic Left Gain" 0x20, 0x20, 16, 16, 0x0, 0xF, 0x1F, 0, 0, //"Mic Left Gain"
0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, // "Mic Right Gain" 0x20, 0x20, 24, 24, 0x0, 0xF, 0x1F, 0, 0, // "Mic Right Gain"
0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // "Render Channel Mode" 0x2000, 0x2000, 16, 16, 0x0, 0x7, 0x7, 0, 0, // "Render Channel Mode"
0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 // "Capture Channel Mode" 0x1000, 0x1000, 16, 16, 0x0, 0x7, 0x7, 0, 0 //"Capture Channel Mode"
]; ];
/* After the upper layer delivers parameters, write audio-related data to registers. /* After the upper layer delivers parameters, write audio-related data to registers.
...@@ -607,7 +611,7 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec) ...@@ -607,7 +611,7 @@ int32_t CodecDeviceInit(struct AudioCard *audioCard, struct CodecDevice *codec)
## Accessory Driver Development Example<a name="section4200"></a> ### Accessory Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/tfa9879/accessory** Code path: **drivers/peripheral/audio/chipsets/tfa9879/accessory**
SmartPA is a type of accessory driver. The SmartPA development procedure is similar to the codec development procedure. SmartPA is a type of accessory driver. The SmartPA development procedure is similar to the codec development procedure.
...@@ -616,13 +620,13 @@ SmartPA is a type of accessory driver. The SmartPA development procedure is simi ...@@ -616,13 +620,13 @@ SmartPA is a type of accessory driver. The SmartPA development procedure is simi
3. Register and bind the accessory instance to the HDF. 3. Register and bind the accessory instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
### Filling in Accessory Data Structures<a name="section4221"></a> #### Filling in Accessory Data Structures
Fill in the following data structures for the accessory module: Fill in the following data structures for the accessory module:
- **g_tfa9879Data**: operation function set of the accessory device. It contains the configuration in the .hcs file, and defines and maps the functions for initializing the accessory device and reading and writing registers. - **g_tfa9879Data**: operation function set of the accessory device. It contains the configuration in the .hcs file, and defines and maps the functions for initializing the accessory device and reading and writing registers.
- **g_tfa9879DaiDeviceOps**: data set of the accessory device DAI. It defines and maps the operation set of the accessory device DAI. - **g_tfa9879DaiDeviceOps**: data set of the DAI of the accessory device. It defines and maps the operation set of the accessory device DAI.
- **g_tfa9879DaiData**: data set of the DAI of the accessory device. It defines and maps the driver name, initialization, and operation set of the data access interface of the accessory device. - **g_tfa9879DaiData**: data set of the DAI of the accessory device. It defines and maps the driver name, initialization, and operation set of the data access interface of the accessory device.
...@@ -645,7 +649,7 @@ struct DaiData g_tfa9879DaiData = { ...@@ -645,7 +649,7 @@ struct DaiData g_tfa9879DaiData = {
}; };
``` ```
### Initializing the Accessory Device and Accessory DAI Device<a name="section4222"></a> #### Initializing accessoryDevice and accessoryDai
As the entry function for device initialization, **Tfa9879DeviceInit** sets the address of the SmartPA I2C device, obtains configuration data, initializes (including resets) the device registers, and adds the control functionality to the controller linked list. The current demo also includes the initialization of the registers related to the Hi3516D V300 device, such as initialization of GPIO pins. As the entry function for device initialization, **Tfa9879DeviceInit** sets the address of the SmartPA I2C device, obtains configuration data, initializes (including resets) the device registers, and adds the control functionality to the controller linked list. The current demo also includes the initialization of the registers related to the Hi3516D V300 device, such as initialization of GPIO pins.
...@@ -696,7 +700,7 @@ int32_t AccessoryI2cReadWrite(struct AudioAddrConfig *regAttr, uint16_t rwFlag) ...@@ -696,7 +700,7 @@ int32_t AccessoryI2cReadWrite(struct AudioAddrConfig *regAttr, uint16_t rwFlag)
} }
``` ```
### Implementing the Accessory Operation Function Set<a name="section4223"></a> #### Implementing the Accessory Operation Function Set
The callbacks **AccessoryDeviceRegRead** and **AccessoryDeviceRegWrite** invoke **AccessoryI2cReadWrite** to read and write the control register values. The callbacks **AccessoryDeviceRegRead** and **AccessoryDeviceRegWrite** invoke **AccessoryI2cReadWrite** to read and write the control register values.
...@@ -759,7 +763,7 @@ int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHw ...@@ -759,7 +763,7 @@ int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHw
(void)card; (void)card;
... ...
// Set the sampling rate. // Set the sampling rate.
ret = AcessoryDeviceFrequencyParse(param->rate, &frequency); ret = AccessoryDeviceFrequencyParse(param->rate, &frequency);
... ...
// Set the bit width. // Set the bit width.
ret = Tfa9879FormatParse(param->format, &bitWidth); ret = Tfa9879FormatParse(param->format, &bitWidth);
...@@ -773,7 +777,7 @@ int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHw ...@@ -773,7 +777,7 @@ int32_t Tfa9879DaiHwParams(const struct AudioCard *card, const struct AudioPcmHw
} }
``` ```
### Registering and Binding Accessory to HDF<a name="section4224"></a> #### Registering and Binding Accessory to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md). This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md).
...@@ -814,13 +818,13 @@ struct HdfDriverEntry g_tfa9879DriverEntry = { ...@@ -814,13 +818,13 @@ struct HdfDriverEntry g_tfa9879DriverEntry = {
HDF_INIT(g_tfa9879DriverEntry); HDF_INIT(g_tfa9879DriverEntry);
``` ```
### Configuring HCS<a name="section4225"></a> #### Configuring HCS
For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**. For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**.
## Platform Driver Development Example<a name="section4300"></a> ### Platform Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/soc** Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/soc**
In audio driver development, the Platform module is configured to adapt to the DMA driver. The major steps for developing the platform driver are as follows: In audio driver development, the Platform module is configured to adapt to the DMA driver. The major steps for developing the platform driver are as follows:
...@@ -829,7 +833,7 @@ In audio driver development, the Platform module is configured to adapt to the D ...@@ -829,7 +833,7 @@ In audio driver development, the Platform module is configured to adapt to the D
3. Register and bind the platform instance to the HDF. 3. Register and bind the platform instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
### Filling in Platform Data Structures<a name="section4331"></a> #### Filling in Platform Data Structures
Fill in the following structures for the platform module: Fill in the following structures for the platform module:
...@@ -857,7 +861,7 @@ struct PlatformData g_platformData = { ...@@ -857,7 +861,7 @@ struct PlatformData g_platformData = {
}; };
``` ```
### Initializing the DMA Device<a name="section4332"></a> #### Initializing dmaDevice
**AudioDmaDeviceInit** initializes the DMA device, including setting the Hi3516 AIAO module. **AudioDmaDeviceInit** initializes the DMA device, including setting the Hi3516 AIAO module.
...@@ -877,7 +881,7 @@ int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDe ...@@ -877,7 +881,7 @@ int32_t AudioDmaDeviceInit(const struct AudioCard *card, const struct PlatformDe
} }
``` ```
### Implementing the DMA Operation Function Set<a name="section4333"></a> #### Implementing the DMA Operation Function Set
The DMA device operation function set includes the encapsulation of DMA common APIs. If the common APIs cannot meet development requirements, you can implement new DMA callbacks. The DMA device operation function set includes the encapsulation of DMA common APIs. If the common APIs cannot meet development requirements, you can implement new DMA callbacks.
...@@ -894,7 +898,7 @@ int32_t Hi3516DmaResume(const struct PlatformData *data); ...@@ -894,7 +898,7 @@ int32_t Hi3516DmaResume(const struct PlatformData *data);
int32_t Hi3516DmaPointer(struct PlatformData *data, uint32_t *pointer); int32_t Hi3516DmaPointer(struct PlatformData *data, uint32_t *pointer);
``` ```
### Registering and Binding Platform to HDF<a name="section4334"></a> #### Registering and Binding Platform to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md). This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md).
...@@ -938,13 +942,13 @@ struct HdfDriverEntry g_platformDriverEntry = { ...@@ -938,13 +942,13 @@ struct HdfDriverEntry g_platformDriverEntry = {
HDF_INIT(g_platformDriverEntry); HDF_INIT(g_platformDriverEntry);
``` ```
### Configuring HCS<a name="section4335"></a> #### Configuring HCS
For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**. For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**.
## DAI Driver Development Example<a name="section4400"></a> ### DAI Driver Development Example
Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/soc** Code path: **drivers/peripheral/audio/chipsets/hi3516dv300/soc**
The major steps for developing the DAI driver are as follows: The major steps for developing the DAI driver are as follows:
...@@ -953,7 +957,7 @@ The major steps for developing the DAI driver are as follows: ...@@ -953,7 +957,7 @@ The major steps for developing the DAI driver are as follows:
3. Register and bind the DAI instance to the HDF. 3. Register and bind the DAI instance to the HDF.
4. Configure the HCS and makefile. 4. Configure the HCS and makefile.
### Filling in DAI Data Structures<a name="section4441"></a> #### Filling in DAI Data Structures
Fill in the following structures for the DAI module: Fill in the following structures for the DAI module:
...@@ -976,7 +980,7 @@ struct DaiData g_daiData = { ...@@ -976,7 +980,7 @@ struct DaiData g_daiData = {
}; };
``` ```
### Initializing the DAI Device<a name="section4442"></a> #### Initializing daiDevice
**DaiDeviceInit** initializes DAI configuration and adds the information to the controller linked list. **DaiDeviceInit** initializes DAI configuration and adds the information to the controller linked list.
...@@ -999,7 +1003,7 @@ int32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai) ...@@ -999,7 +1003,7 @@ int32_t DaiDeviceInit(struct AudioCard *audioCard, const struct DaiDevice *dai)
} }
``` ```
### Implementing the DAI Operation Function Set<a name="section4443"></a> #### Implementing the DAI Operation Function Set
**AudioDeviceReadReg** and **AudioDeviceWriteReg** are not used on the Hi3516 and are reserved. **AudioDeviceReadReg** and **AudioDeviceWriteReg** are not used on the Hi3516 and are reserved.
...@@ -1058,7 +1062,7 @@ int32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device) ...@@ -1058,7 +1062,7 @@ int32_t DaiStartup(const struct AudioCard *card, const struct DaiDevice *device)
} }
``` ```
### Registering and Binding DAI to HDF<a name="section4444"></a> #### Registering and Binding DAI to HDF
This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md). This process depends on the driver implementation mode of the HDF. For details, see [HDF](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf.md).
...@@ -1114,13 +1118,13 @@ struct HdfDriverEntry g_daiDriverEntry = { ...@@ -1114,13 +1118,13 @@ struct HdfDriverEntry g_daiDriverEntry = {
HDF_INIT(g_daiDriverEntry); HDF_INIT(g_daiDriverEntry);
``` ```
### Configuring HCS<a name="section4445"></a> #### Configuring HCS
For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**. For details about the configuration process, see [Configuring HCS](#section4115) in **Codec Driver Development Example**.
## Adding Compilation Configuration to Makefile<a name="section4500"></a> ### Adding Compilation Configuration to Makefile
Add the newly added files to the **Makefile** file to link them to the kernel image. Add the newly added files to the **Makefile** file to link them to the kernel image.
...@@ -1161,11 +1165,11 @@ $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c ...@@ -1161,11 +1165,11 @@ $(KHDF_AUDIO_HI3516DV300_DIR)/soc/src/hi3516_dma_adapter.c
## Source Code Structure and Directory<a name="section4600"></a> ### Source Code Structure and Directory
The development example implements the functions in the header file of the driver interface. The following uses Hi3516 as an example to describe the directory structure. The development example implements the functions in the header file of the driver interface. The following uses Hi3516 as an example to describe the directory structure.
Path of the driver implementation sample code: **drivers/peripheral/audio/chipsets** Path of the driver implementation sample code: **drivers\peripheral\audio\chipsets\**
``` ```
├── hi3516dv300 ├── hi3516dv300
...@@ -1241,10 +1245,15 @@ vendor/hisilicon/hispark_taurus/ ...@@ -1241,10 +1245,15 @@ vendor/hisilicon/hispark_taurus/
# HAL-based Development Procedure and Example<a name="section5000"></a> ## HAL-based Development Procedure and Example
The Hardware Abstraction Layer (HAL) provides the following functions:
1. Provides audio HDIs for audio services to implement basic audio features on applications.
2. Provides standard interfaces for device developers to comply with the HDI adapter standards. This promises a healthy evolution of the ecosystem.
Code path: **drivers/peripheral/audio/hal** Code path: **drivers/peripheral/audio/hal**
## Development Procedure<a name="section5100"></a> ### Development procedure
![](figures/HAL_flowchart.png) ![](figures/HAL_flowchart.png)
...@@ -1266,7 +1275,7 @@ Code path: **drivers/peripheral/audio/hal** ...@@ -1266,7 +1275,7 @@ Code path: **drivers/peripheral/audio/hal**
3. manager->UnloadAdapter(); 3. manager->UnloadAdapter();
## Development Example<a name="section5200"></a> ### Development Example
```c ```c
#include <string.h> #include <string.h>
...@@ -1354,6 +1363,6 @@ static void *hal_main() ...@@ -1354,6 +1363,6 @@ static void *hal_main()
# Summary<a name="section9999"></a> ## Summary
This document provides all the key adaptations involved in the driver development based on the audio driver architecture. It elaborates how to adapt the audio driver and use HDI APIs. You can easily develop your audio drivers based on the chip you use by referring to this document. This document provides all the key adaptations involved in the audio driver development. It elaborates how to adapt the audio driver and use HDI APIs. You can conduct development based on the chip you use. After reading this document, you will be able to master the audio driver development based on the HDF framework.
# Camera<a name="EN-US_TOPIC_0000001242747077"></a> # Camera
## Overview ## Overview<a name="1"></a>
### Camera<a name="2"></a>
The OpenHarmony camera driver model implements the camera hardware driver interface \(HDI\) and the camera pipeline model to manage camera devices.
The OpenHarmony camera driver model implements the camera hardware device interface (HDI) and the camera pipeline model to manage camera devices.
The camera driver model consists of the following layers: The camera driver model consists of the following layers:
- HDI implementation layer: implements standard southbound interfaces of OpenHarmony cameras. + HDI implementation layer: implements standard ohos (OpenHarmony operating system) APIs for cameras.
+ Framework layer: connects to the HDI implementation layer for control instruction and stream transfer, establishes data channels, and manages camera devices.
+ Device adaptation layer: shields the differences between underlying chips and OSs for multi-platform adaptation.
- Framework layer: connects to the HDI implementation layer for control instruction and stream transfer, establishes data channels, and manages camera devices. ### Working Principles<a name="3"></a>
- Adaptation layer: shields the differences between bottom-layer chips and OSs for multi-platform adaptation. The camera module is used to initialize services and devices, set up data channels, and configure, create, deliver, and capture streams. The figure below illustrates camera driver model.
**Figure 1** HDF-based camera driver model
**Figure 1** Architecture of the camera driver model ![](figures/camera-driver-model-architecture.png)
![](figures/camera-driver-model-architecture.png "camera-driver-model-architecture")
1. The CameraDeviceHost process is created during system startup. The process enumerates underlying devices, creates a **DeviceManager** instance that manages the device tree, an object for each underlying device, and a **CameraHost** instance, and registers the **CameraHost** instance with the UHDF service. Through this service, the upper layer can obtain the CameraDeviceHost process at the bottom layer to operate the underlying devices. Note that the **DeviceManager** instance can also be created by using the configuration table. 1. When the system starts, the camera_host process is created. The process enumerates underlying devices, creates a **DeviceManager** instance that manages the device tree, an object for each underlying device, and a **CameraHost** instance, and registers the **CameraHost** instance with the UHDF service. Through the UHDF service, the camera service can obtain the underlying **CameraDeviceHost** services to operate the hardware devices. Note that the **DeviceManager** instance can also be created by using the configuration table.
2. The Camera Service obtains the **CameraHost** instance through the CameraDeviceHost service. The **CameraHost** instance can be used to obtain the bottom-layer camera capabilities, turn on the flashlight, call the **Open\(\)** interface to start the camera and create a connection, create a **DeviceManager** instance \(powering on the bottom-layer hardware modules\), and create a **CameraDevice** instance \(providing the device control interface for the upper layer\). When the **CameraDevice** instance is created, each submodule of PipelineCore is instantiated. Among the submodules, StreamPiplineCore is responsible for creating pipelines, and MetaQueueManager is responsible for reporting metadata. 2. The Camera Service obtains the **CameraHost** instance through the CameraDeviceHost service. The **CameraHost** instance can be used to obtain the bottom-layer camera capabilities, turn on the flashlight, call the **Open()** interface to start the camera and create a connection, create a **DeviceManager** instance (powering on the bottom-layer hardware modules), and create a **CameraDevice** instance (providing the device control interface for the upper layer). When the **CameraDevice** instance is created, each submodule of PipelineCore is instantiated. Among the submodules, StreamPipelineCore is responsible for creating pipelines, and MetaQueueManager is responsible for reporting metadata.
3. The Camera Service configures the stream and creates a **Stream** instance through the **CameraDevice** instance at the bottom layer. The StreamPipelineStrategy module creates the node connection mode of the corresponding stream by using the mode issued by the upper layer and querying the configuration table. The StreamPipelineBuilder module creates a node and returns the pipeline to the StreamPipelineDispatcher module through the connection. The StreamPipelineDispatcher module provides unified pipeline invoking management. 3. The Camera Service configures stream and creates a **Stream** class through the CameraDevice module. The StreamPipelineStrategy module creates the node connection mode of the corresponding stream by using the mode issued by the upper layer and querying the configuration table. The StreamPipelineBuilder module creates a node and returns the pipeline to the StreamPipelineDispatcher module through the connection. The StreamPipelineDispatcher module dispatches pipelines.
4. The Camera Service controls the stream operations through the **Stream** instance. The **AttachBufferQueue\(\)** interface is used to deliver the buffer queue requested from the display module to the bottom layer. The CameraDeviceDriverModel manages the buffer. After the **Capture\(\)** interface is called to deliver commands, the bottom layer transfers the buffer to the upper layer. The Image Signal Processor \(ISP\) node obtains a specified number of buffers from the buffer queue and delivers the buffers to the bottom-layer ISP hardware. After filling the buffers, the ISP hardware transfers the buffers to the CameraDeviceDriverModel. The CameraDeviceDriverModel fills the created pipeline with the received buffers by using a loop thread. Each node processes the pipeline data and transfers the data to the upper layer by using a callback. At the same time, the buffers are freed for reuse. 4. The Camera Service controls the stream operations through the **Stream** instance. The **AttachBufferQueue()** interface is used to deliver the buffer queue requested from the display module to the bottom layer. The CameraDeviceDriverModel manages the buffer. After the **Capture()** interface is called to deliver commands, the bottom layer transfers the buffer to the upper layer. The Image Signal Processor (ISP) node obtains a specified number of buffers from the buffer queue and delivers the buffers to the bottom-layer ISP hardware. After filling the buffers, the ISP hardware transfers the buffers to the CameraDeviceDriverModel. The CameraDeviceDriverModel fills the created pipeline with the received buffers by using a loop thread. Each node processes the pipeline data and transfers the data to the upper layer by using a callback. At the same time, the buffers are freed for reuse.
5. The Camera Service delivers the photographing command through the **Capture\(\)** interface. The **ChangeToOfflineStream\(\)** interface is used to query the position of the photographing buffer. If the ISP hardware has output an image and sent the image data to the IPP node, the common photographing streams can be converted into offline streams. Otherwise, the close process is executed. The **ChangeToOfflineStream\(\)** interface transfers **StreamInfo** to enable the offline stream to obtain the stream information of the common stream, confirms the node connection mode of the offline stream based on the configuration table, and creates the node connection of the offline stream. If the node connection has been created, the interface releases the node required by the non-offline stream through **CloseCamera\(\)**. It then waits for the buffer to return from the bottom-layer pipeline to the upper layer and then releases the pipeline resources. 5. The Camera Service delivers the photographing command through the **Capture()** interface. The **ChangeToOfflineStream()** interface is used to query the position of the photographing buffer. If the ISP hardware has output an image and sent the image data to the IPP node, the common photographing streams can be converted into offline streams. Otherwise, the close process is executed. The **ChangeToOfflineStream()** interface transfers **StreamInfo** to enable the offline stream to obtain the stream information of the common stream, confirms the node connection mode of the offline stream based on the configuration table, and creates the node connection of the offline stream. If the node connection has been created, the interface releases the node required by the non-offline stream through **CloseCamera()**. It then waits for the buffer to return from the bottom-layer pipeline to the upper layer and then releases the pipeline resources.
6. The Camera Service sends the **CaptureSetting** parameter to the CameraDeviceDriverModel through the **UpdateSettings\(\)** interface of the **CameraDevice** instance. The CameraDeviceDriverModel forwards the parameter to each node through the StreamPipelineDispatcher module. The **CaptureSetting** parameter carried in the **StartStreamingCapture\(\)** and **Capture\(\)** interfaces is forwarded to the node to which the stream belongs through the StreamPipelineDispatcher module. 6. The Camera Service sends the **CaptureSetting** parameter to the CameraDeviceDriverModel through the **UpdateSettings()** interface of the **CameraDevice** instance. The CameraDeviceDriverModel forwards the parameter to each node through the StreamPipelineDispatcher module. The **CaptureSetting** parameter carried in **StartStreamingCapture()** and **Capture()** is forwarded to the node to which the stream belongs through the StreamPipelineDispatcher module.
7. The Camera Service controls underlying metadata reporting through the **EnableResult\(\)** and **DisableResult\(\)** interfaces. If the bottom-layer metadata needs to be reported, the pipeline creates a buffer queue in the CameraDeviceDriverModel to collect and transfer metadata, queries the configuration table based on the StreamPipelineStrategy module, and creates and connects to the specified node through the StreamPipelineBuilder module. The MetaQueueManager module delivers the buffer to the bottom layer, and the bottom-layer node fills in data. The MetaQueueManager module then invokes the upper-layer callback to transfer the data to the upper layer. 7. The Camera Service controls underlying metadata reporting through the **EnableResult()** and **DisableResult()** interfaces. If the underlying metadata needs to be reported, the pipeline creates a buffer queue in the CameraDeviceDriverModel to collect and transfer metadata, queries the configuration table based on the StreamPipelineStrategy module, and creates and connects to the specified node through the StreamPipelineBuilder module. The MetaQueueManager module delivers the buffer to the bottom layer, and the bottom-layer node fills in data. The MetaQueueManager module then invokes the upper-layer callback to transfer the data to the upper layer.
8. The Camera Service calls the **Close\(\)** interface of the **CameraDevice** class, and the **CameraDevice** instance calls the corresponding DeviceManager module to power off each hardware. If an offline stream exists in the subpipeline of the IPP node, the offline stream must be reserved until the execution is complete. 8. The Camera Service calls the **Close()** interface of the **CameraDevice** class, and the **CameraDevice** instance calls the corresponding DeviceManager module to power off each hardware. If an offline stream exists in the subpipeline of the IPP node, the offline stream must be reserved until the execution is complete.
9. To implement dynamic frame control, a CollectBuffer thread is started in the StreamOperator. The CollectBuffer thread obtains a buffer from the buffer queue of each stream. If the frame rate of a stream needs to be controlled \(1/n of the sensor output frame rate\), the CollectBuffer thread can control the buffer packaging of each frame as required, and determine whether to collect the buffer of the stream. For example, if the output frame rate of the sensor is 120 fps and the preview stream frame rate is 30 fps, the CollectBuffer thread collects the buffer of the preview stream every 4 fps. 9. To implement dynamic frame control, a CollectBuffer thread is started in the StreamOperator. The CollectBuffer thread obtains a buffer from the buffer queue of each stream. If the frame rate of a stream needs to be controlled (1/n of the sensor output frame rate), the CollectBuffer thread can control the buffer packaging of each frame as required, and determine whether to collect the buffer of the stream. For example, if the output frame rate of the sensor is 120 fps and the preview stream frame rate is 30 fps, the CollectBuffer thread collects the buffer of the preview stream every 4 fps.
## Development Guidelines ## Development Guidelines<a name="4"></a>
### Available APIs
For details about the HDI functionalities and the function passing rules, see "Available APIs" in [Camera](https://gitee.com/openharmony/drivers_peripheral/blob/master/camera/README_zh.md). ### When to Use<a name="5"></a>
### How to Develop The camera module encapsulates camera operations in camera preview, photographing, and video streams to facilitate camera hardware operations and improve development efficiency.
The following describes the main APIs of the camera driver model, including the APIs for registering and detecting cameras, creating, capturing, and destroying streams, and enabling and disabling devices. \(To clearly describe the implementation of main functionalities, some error judgment and log source code are not described here.\) ### Available APIs<a name="6"></a>
1. Register a **CameraHost**. - icamera_device.h
Define the **HdfDriverEntry** structure to define the method for initializing a **CameraHost**. | API | Description |
| ------------------------------------------------------------ | ---------------------------- |
| CamRetCode GetStreamOperator(<br> const OHOS::sptr<IStreamOperatorCallback> &callback,<br> OHOS::sptr<IStreamOperator> &streamOperator) | Obtains the stream controller. |
| CamRetCode UpdateSettings(const std::shared_ptr<CameraSetting> &settingss) | Updates device control parameters. |
| CamRetCode SetResultMode(const ResultCallbackMode &mode) | Sets the result callback mode and function.|
| CamRetCode GetEnabledResults(std::vector<MetaType> &results) | Obtains the enabled ResultMeta. |
| CamRetCode EnableResult(const std::vector<MetaType> &results) | Enables specific ResultMeta. |
| CamRetCode DisableResult(const std::vector<MetaType> &results) | Disables specific ResultMeta. |
| void Close() | Closes the camera device. |
``` - icamera_device_callback.h
struct HdfDriverEntry g_cameraHostDriverEntry = {
.moduleVersion = 1,
.moduleName = "camera_service",
.Bind = HdfCameraHostDriverBind,
.Init = HdfCameraHostDriverInit,
.Release = HdfCameraHostDriverRelease,
};
HDF_INIT(g_cameraHostDriverEntry); // Register the HdfDriverEntry structure with the HDF.
```
2. Initialize the **CameraHost**. | API | Description |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| void OnError(ErrorType type, int32_t errorCode) | Called when an error occurs on the device to return error information. You need to implement this interface.|
| void OnResult(uint64_t timestamp, const std::shared_ptr<CameraMetadata> &result) | Callback invoked to report metadata related to the camera device. |
**HdfCameraHostDriverBind** defined in the **HdfDriverEntry** structure provides the registration of **CameraServiceDispatch\(\)** and **CameraHostStubInstance\(\)**. **CameraServiceDispatch\(\)** is used to remotely call a method of the **CameraHost**, such as **OpenCamera\(\)** and **SetFlashlight\(\)**. **CameraHostStubInstance\(\)** is used to initialize the camera device, which is called during system startup.
``` - icamera_host.h
int HdfCameraHostDriverBind(HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfCameraHostDriverBind enter!");
if (deviceObject == nullptr) {
HDF_LOGE("HdfCameraHostDriverBind: HdfDeviceObject is NULL !");
return HDF_FAILURE;
}
HdfCameraService *hdfCameraService = reinterpret_cast<HdfCameraService *>(OsalMemAlloc(sizeof(HdfCameraService)));
if (hdfCameraService == nullptr) {
HDF_LOGE("HdfCameraHostDriverBind OsalMemAlloc HdfCameraService failed!");
return HDF_FAILURE;
}
hdfCameraService->ioservice.Dispatch = CameraServiceDispatch; // Used to call methods of the CameraHost.
hdfCameraService->ioservice.Open = nullptr;
hdfCameraService->ioservice.Release = nullptr;
hdfCameraService->instance = CameraHostStubInstance(); // Initialize the camera device.
deviceObject->service = &hdfCameraService->ioservice;
return HDF_SUCCESS;
}
```
The following functions are the implementation of the methods of the **CameraHost**: | API | Description |
| ------------------------------------------------------------ | ------------------------------ |
| CamRetCode SetCallback(const OHOS::sptr<ICameraHostCallback> &callback) | Sets the **ICameraHostCallback** API. |
| CamRetCode GetCameraIds(std::vector\<std::string\> &cameraIds) | Obtains the IDs of available camera devices.|
| CamRetCode GetCameraAbility(const std::string &cameraId,<br> std::shared_ptr<CameraAbility> &ability) | Obtains the abilities of a camera device. |
| CamRetCode OpenCamera(const std::string &cameraId,<br> const OHOS::sptr<ICameraDeviceCallback> &callback,<br> OHOS::sptr<ICameraDevice> &device) | Opens a camera. |
| CamRetCode SetFlashlight(const std::string &cameraId, bool &isEnable) | Turns on or off the flash. |
``` - icamera_host_callback.h
int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data,
MessageParcel &reply, MessageOption &option)
{
switch(cmdId) {
case CMD_CAMERA_HOST_SET_CALLBACK: {
return CameraHostStubSetCallback(data, reply, option);
}
case CMD_CAMERA_HOST_GET_CAMERAID: {
return CameraHostStubGetCameraIds(data, reply, option);
}
case CMD_CAMERA_HOST_GET_CAMERA_ABILITY: {
return CameraHostStubGetCameraAbility(data, reply, option);
}
case CMD_CAMERA_HOST_OPEN_CAMERA: {
return CameraHostStubOpenCamera(data, reply, option);
}
case CMD_CAMERA_HOST_SET_FLASH_LIGHT: {
return CameraHostStubSetFlashlight(data, reply, option);
}
default: {
HDF_LOGE("%s: not support cmd %d", __func__, cmdId);
return HDF_ERR_INVALID_PARAM;
}
}
return HDF_SUCCESS;
}
```
**CameraHostStubInstance\(\)** finally calls **CameraHostImpl::Init\(\)** to obtain the physical camera and initialize the DeviceManager and PipelineCore modules. | API | Description |
| ------------------------------------------------------------ | ---------------------- |
| void OnCameraStatus(const std::string &cameraId, CameraStatus status) | Reports camera status changes.|
| void OnFlashlightStatus(const std::string &cameraId, FlashlightStatus status) | Callback invoked to report the flash status changes. |
3. Obtain the **CamerHost**. - ioffline_stream_operator.h
Call the **Get\(\)** interface to obtain the **CameraHost** from the **CameraService**. The **Get\(\)** interface is as follows: | API | Description |
| ------------------------------------------------------------ | -------------- |
| CamRetCode CancelCapture(int captureId) | Cancels a capture request. |
| CamRetCode ReleaseStreams(const std::vector<int> &streamIds) | Releases streams. |
| CamRetCode Release() | Releases all offline streams.|
``` - istream_operator.h
sptr<ICameraHost> ICameraHost::Get(const char *serviceName)
{
do {
using namespace OHOS::HDI::ServiceManager::V1_0;
auto servMgr = IServiceManager::Get();
if (servMgr == nullptr) {
HDF_LOGE("%s: IServiceManager failed!", __func__);
break;
}
auto remote = servMgr->GetService(serviceName); // Obtain the CameraHost based on serviceName.
if (remote != nullptr) {
sptr<CameraHostProxy> hostSptr = iface_cast<CameraHostProxy>(remote); // Return the CameraHostProxy object that contains methods such as OpenCamera() to the caller.
return hostSptr;
}
HDF_LOGE("%s: GetService failed! serviceName = %s", __func__, serviceName);
} while(false);
HDF_LOGE("%s: get %s failed!", __func__, serviceName);
return nullptr;
}
```
4. Implement the **OpenCamera\(\)** interface. | API | Description |
| ------------------------------------------------------------ | -------------------------------- |
| CamRetCode IsStreamsSupported(<br> OperationMode mode,<br> const std::shared_ptr\<CameraStandard::CameraMetadata\> &modeSetting,<br> const std::vector&ltstd::shared_ptr&ltStreamInfo&gt> &info,<br> StreamSupportType &type) | Checks whether a stream can be added. |
| CamRetCode CreateStreams(const std::vector<std::shared_ptr<StreamInfo>> &streamInfos) | Creates streams. |
| CamRetCode ReleaseStreams(const std::vector<int> &streamIds) | Releases streams. |
| CamRetCode CommitStreams(OperationMode mode,<br> const std::shared_ptr<CameraMetadata> &modeSetting) | Configure streams. |
| CamRetCode GetStreamAttributes(<br> std::vector<std::shared_ptr<StreamAttribute>> &attributes) | Obtain stream attributes. |
| CamRetCode AttachBufferQueue(int streamId, const OHOS::sptr\<OHOS::IBufferProducer\> &producer) | Attaches a producer handle to a stream. |
| CamRetCode DetachBufferQueue(int streamId) | Detaches a producer handle from a stream.|
| CamRetCode Capture(int captureId,<br> const std::shared_ptr<CaptureInfo> &info, bool isStreaming) | Captures images. |
| CamRetCode CancelCapture(int captureId) | Cancels a capture. |
| CamRetCode ChangeToOfflineStream(const std::vector<int> &streamIds,<br> OHOS::sptr<IStreamOperatorCallback> &callback,<br> OHOS::sptr<IOfflineStreamOperator> &offlineOperator) | Changes a stream into an offline stream. |
The **CameraHostProxy** class provides five interfaces: **SetCallback\(\)**, **GetCameraIds\(\)**, **GetCameraAbility\(\)**, **OpenCamera\(\)**, and **SetFlashlight\(\)**. The following describes **OpenCamera\(\)**. - istream_operator_callback.h
The **OpenCamera\(\)** interface calls the remote **CameraHostStubOpenCamera\(\)** interface through the CMD\_CAMERA\_HOST\_OPEN\_CAMERA to obtain an **ICameraDevice** object. | API | Description |
| ------------------------------------------------------------ | ---------------------------------------- |
| void OnCaptureStarted(int32_t captureId, const std::vector<int32_t> &streamIds) | Called when a capture starts. |
| void OnCaptureEnded(int32_t captureId,<br> const std::vector<std::shared_ptr<CaptureEndedInfo>> &infos) | Called when a capture ends. |
| void OnCaptureError(int32_t captureId,<br> const std::vector<std::shared_ptr<CaptureErrorInfo>> &infos) | Called when an error occurs during the capture.|
| void OnFrameShutter(int32_t captureId,<br> const std::vector<int32_t> &streamIds, uint64_t timestamp) | Called when a frame is captured. |
``` ### How to Develop<a name="7"></a>
CamRetCode CameraHostProxy::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &pDevice) To camera driver development procedure is as follows:
{
int32_t ret = Remote()->SendRequest(CMD_CAMERA_HOST_REMOTE_OPEN_CAMERA, data, reply, option);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret);
return INVALID_ARGUMENT;
}
CamRetCode retCode = static_cast<CamRetCode>(reply.ReadInt32());
bool flag = reply.ReadBool();
if (flag) {
sptr<IRemoteObject> remoteCameraDevice = reply.ReadRemoteObject();
if (remoteCameraDevice == nullptr) {
HDF_LOGE("%{public}s: CameraHostProxy remoteCameraDevice is null", __func__);
}
pDevice = OHOS::iface_cast<ICameraDevice>(remoteCameraDevice);
}
return retCode;
}
```
**Remote\(\)-\>SendRequest** calls **CameraHostServiceStubOnRemoteRequest\(\)**, enters the **CameraHostStubOpenCamera\(\)** interface based on **cmdId**, and finally calls **CameraHostImpl::OpenCamera\(\)** to obtain a **CameraDevice** and power on the camera hardware. 1. Register a **CameraHost**.
Define the **HdfDriverEntry** structure to define the method for initializing a **CameraHost**.
``` ```
CamRetCode CameraHostImpl::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &device) struct HdfDriverEntry g_cameraHostDriverEntry = {
{ .moduleVersion = 1,
std::shared_ptr<CameraDeviceImpl> cameraDevice = std::static_pointer_cast<CameraDeviceImpl>(itr->second); .moduleName = "camera_service",
if (cameraDevice == nullptr) { .Bind = HdfCameraHostDriverBind,
CAMERA_LOGE("camera device is null."); .Init = HdfCameraHostDriverInit,
return INSUFFICIENT_RESOURCES; .Release = HdfCameraHostDriverRelease,
} };
CamRetCode ret = cameraDevice->SetCallback(callback); HDF_INIT(g_cameraHostDriverEntry); // Register the HdfDriverEntry structure with the HDF.
if (ret != NO_ERROR) { ```
CAMERA_LOGW("set camera device callback faild.");
return ret;
}
CameraHostConfig *config = CameraHostConfig::GetInstance();
if (config == nullptr) {
return INVALID_ARGUMENT;
}
std::vector<std::string> phyCameraIds;
RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds);
if (rc != RC_OK) {
CAMERA_LOGE("get physic cameraId failed.");
return DEVICE_ERROR;
}
if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) { // Power on the camera hardware.
CAMERA_LOGE("camera powerup failed.");
CameraPowerDown(phyCameraIds);
return DEVICE_ERROR;
}
auto sptrDevice = deviceBackup_.find(cameraId);
if (sptrDevice == deviceBackup_.end()) {
deviceBackup_[cameraId] = cameraDevice.get();
}
device = deviceBackup_[cameraId];
cameraDevice->SetStatus(true);
return NO_ERROR;
}
```
5. Implement the **GetStreamOperator\(\)** interface. 2. Initialize the **CameraHost**.
**CameraDeviceImpl** defines interfaces such as **GetStreamOperator\(\)**, **UpdateSettings\(\)**, **SetResultMode\(\)**, and **GetEnabledResult\(\)**. The following is an example of implementing the **GetStreamOperator\(\)** interface:
```
CamRetCode CameraDeviceImpl::GetStreamOperator(const OHOS::sptr<IStreamOperatorCallback> &callback,
OHOS::sptr<IStreamOperator> &streamOperator)
{
if (callback == nullptr) {
CAMERA_LOGW("input callback is null.");
return INVALID_ARGUMENT;
}
spCameraDeciceCallback_ = callback;
if (spStreamOperator_ == nullptr) {
// Here, an spStreamOperator object is created and passed to the caller for stream operations.
spStreamOperator_ = new(std::nothrow) StreamOperatorImpl(spCameraDeciceCallback_, shared_from_this());
if (spStreamOperator_ == nullptr) {
CAMERA_LOGW("create stream operator failed.");
return DEVICE_ERROR;
}
ismOperator_ = spStreamOperator_;
}
streamOperator = ismOperator_;
spStreamOperator_->SetRequestCallback([this](){
cameraDeciceCallback_->OnError(REQUEST_TIMEOUT, 0);
});
}
```
6. Create a stream.
Fill in the **StreamInfo** structure before creating a stream by calling **CreateStreams\(\)**. **HdfCameraHostDriverBind** defined in the **HdfDriverEntry** structure provides the registration of **CameraServiceDispatch()** and **CameraHostStubInstance()**. **CameraServiceDispatch()** is used to remotely call a method of the **CameraHost**, such as **OpenCamera()** and **SetFlashlight()**. **CameraHostStubInstance()** is used to initialize the camera device, which is called during system startup.
```
int HdfCameraHostDriverBind(HdfDeviceObject *deviceObject)
{
HDF_LOGI("HdfCameraHostDriverBind enter!");
if (deviceObject == nullptr) {
HDF_LOGE("HdfCameraHostDriverBind: HdfDeviceObject is NULL !");
return HDF_FAILURE;
}
HdfCameraService *hdfCameraService = reinterpret_cast<HdfCameraService *>(OsalMemAlloc(sizeof(HdfCameraService)));
if (hdfCameraService == nullptr) {
HDF_LOGE("HdfCameraHostDriverBind OsalMemAlloc HdfCameraService failed!");
return HDF_FAILURE;
}
hdfCameraService->ioservice.Dispatch = CameraServiceDispatch; // Used to call methods of the CameraHost.
hdfCameraService->ioservice.Open = nullptr;
hdfCameraService->ioservice.Release = nullptr;
hdfCameraService->instance = CameraHostStubInstance(); // Initialize the camera device.
deviceObject->service = &hdfCameraService->ioservice;
return HDF_SUCCESS;
}
```
The following functions are the implementation of the methods of the **CameraHost**:
```
int32_t CameraHostStub::CameraHostServiceStubOnRemoteRequest(int cmdId, MessageParcel &data,
MessageParcel &reply, MessageOption &option)
{
switch(cmdId) {
case CMD_CAMERA_HOST_SET_CALLBACK: {
return CameraHostStubSetCallback(data, reply, option);
}
case CMD_CAMERA_HOST_GET_CAMERAID: {
return CameraHostStubGetCameraIds(data, reply, option);
}
case CMD_CAMERA_HOST_GET_CAMERA_ABILITY: {
return CameraHostStubGetCameraAbility(data, reply, option);
}
case CMD_CAMERA_HOST_OPEN_CAMERA: {
return CameraHostStubOpenCamera(data, reply, option);
}
case CMD_CAMERA_HOST_SET_FLASH_LIGHT: {
return CameraHostStubSetFlashlight(data, reply, option);
}
default: {
HDF_LOGE("%s: not support cmd %d", __func__, cmdId);
return HDF_ERR_INVALID_PARAM;
}
}
return HDF_SUCCESS;
}
```
**CameraHostStubInstance()** finally calls **CameraHostImpl::Init()** to obtain the physical camera and initialize the DeviceManager and PipelineCore modules.
3. Obtain the **CameraHost**.
Call the **Get()** interface to obtain the **CameraHost** from the **CameraService**. The **Get()** interface is as follows:
```
sptr<ICameraHost> ICameraHost::Get(const char *serviceName)
{
do {
using namespace OHOS::HDI::ServiceManager::V1_0;
auto servMgr = IServiceManager::Get();
if (servMgr == nullptr) {
HDF_LOGE("%s: IServiceManager failed!", __func__);
break;
}
auto remote = servMgr->GetService(serviceName); // Obtain the CameraHost based on serviceName.
if (remote != nullptr) {
sptr<CameraHostProxy> hostSptr = iface_cast<CameraHostProxy>(remote); // Return the CameraHostProxy object that contains interfaces such as OpenCamera() to the caller.
return hostSptr;
}
HDF_LOGE("%s: GetService failed! serviceName = %s", __func__, serviceName);
} while(false);
HDF_LOGE("%s: get %s failed!", __func__, serviceName);
return nullptr;
}
```
``` 4. Implement the **OpenCamera\(\)** interface.
using StreamInfo = struct _StreamInfo {
int streamId_;
int width_; // Stream width
int height_; // Stream height
int format_; // Stream format, for example, PIXEL_FMT_YCRCB_420_SP
int datasapce_;
StreamIntent intent_; // StreamIntent, for example, PREVIEW
bool tunneledMode_;
OHOS::sptr<OHOS::IBufferProducer> bufferQueue_; // The stream buffer queue can be created by using the streamCustomer->CreateProducer() interface.
int minFrameDuration_;
EncodeType encodeType_;
};
```
The **CreateStreams\(\)** interface in the **StreamOperatorImpl** class is used to create a **StreamBase** instance, which can then be used to initialize operations such as **CreateBufferPool\(\)** by using the **init\(\)** method. The **CameraHostProxy** class provides five interfaces: **SetCallback()**, **GetCameraIds()**, **GetCameraAbility()**, **OpenCamera()**, and **SetFlashlight()**. The following describes **OpenCamera()**.
The **OpenCamera()** interface calls the remote **CameraHostStubOpenCamera()** interface through the CMD_CAMERA_HOST_OPEN_CAMERA to obtain an **ICameraDevice** object.
```
CamRetCode CameraHostProxy::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &pDevice)
{
int32_t ret = Remote()->SendRequest(CMD_CAMERA_HOST_REMOTE_OPEN_CAMERA, data, reply, option);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%{public}s: SendRequest failed, error code is %{public}d", __func__, ret);
return INVALID_ARGUMENT;
}
CamRetCode retCode = static_cast<CamRetCode>(reply.ReadInt32());
bool flag = reply.ReadBool();
if (flag) {
sptr<IRemoteObject> remoteCameraDevice = reply.ReadRemoteObject();
if (remoteCameraDevice == nullptr) {
HDF_LOGE("%{public}s: CameraHostProxy remoteCameraDevice is null", __func__);
}
pDevice = OHOS::iface_cast<ICameraDevice>(remoteCameraDevice);
}
return retCode;
}
```
**Remote()->SendRequest** calls **CameraHostServiceStubOnRemoteRequest()**, enters the **CameraHostStubOpenCamera()** interface based on **cmdId**, and finally calls **CameraHostImpl::OpenCamera()** to obtain a **CameraDevice** and power on the camera hardware.
```
CamRetCode CameraHostImpl::OpenCamera(const std::string &cameraId, const OHOS::sptr<ICameraDeviceCallback> &callback, OHOS::sptr<ICameraDevice> &device)
{
std::shared_ptr<CameraDeviceImpl> cameraDevice = std::static_pointer_cast<CameraDeviceImpl>(itr->second);
if (cameraDevice == nullptr) {
CAMERA_LOGE("camera device is null.");
return INSUFFICIENT_RESOURCES;
}
CamRetCode ret = cameraDevice->SetCallback(callback);
if (ret != NO_ERROR) {
CAMERA_LOGW("set camera device callback failed.");
return ret;
}
CameraHostConfig *config = CameraHostConfig::GetInstance();
if (config == nullptr) {
return INVALID_ARGUMENT;
}
std::vector<std::string> phyCameraIds;
RetCode rc = config->GetPhysicCameraIds(cameraId, phyCameraIds);
if (rc != RC_OK) {
CAMERA_LOGE("get physic cameraId failed.");
return DEVICE_ERROR;
}
if (CameraPowerUp(cameraId, phyCameraIds) != RC_OK) { // Power on the camera hardware.
CAMERA_LOGE("camera powerup failed.");
CameraPowerDown(phyCameraIds);
return DEVICE_ERROR;
}
auto sptrDevice = deviceBackup_.find(cameraId);
if (sptrDevice == deviceBackup_.end()) {
deviceBackup_[cameraId] = cameraDevice.get();
}
device = deviceBackup_[cameraId];
cameraDevice->SetStatus(true);
return NO_ERROR;
}
```
``` 5. Implement the **GetStreamOperator\(\)** interface.
RetCode StreamOperatorImpl::CreateStream(const std::shared_ptr<StreamInfo>& streamInfo)
{
static std::map<StreamIntent, std::string> typeMap = {
{PREVIEW, "PREVIEW"},
{VIDEO, "VIDEO"},
{STILL_CAPTURE, "STILL_CAPTURE"},
{POST_VIEW, "POST_VIEW"}, {ANALYZE, "ANALYZE"},
{CUSTOM, "CUSTOM"}
};
auto itr = typeMap.find(streamInfo->intent_);
if (itr == typeMap.end()) {
CAMERA_LOGE("do not support stream type. [type = %{public}d]", streamInfo->intent_);
return RC_ERROR;
}
std::shared_ptr<StreamBase> stream = StreamFactory::Instance().CreateShared(itr->second); // Create a StreamBase instance.
RetCode rc = stream->Init(streamInfo);
return RC_OK;
}
```
7. Configure the stream. **CameraDeviceImpl** defines interfaces such as **GetStreamOperator()**, **UpdateSettings()**, **SetResultMode()**, and **GetEnabledResult()**. The following is an example of implementing the **GetStreamOperator()** interface:
```
CamRetCode CameraDeviceImpl::GetStreamOperator(const OHOS::sptr<IStreamOperatorCallback> &callback,
OHOS::sptr<IStreamOperator> &streamOperator)
{
if (callback == nullptr) {
CAMERA_LOGW("input callback is null.");
return INVALID_ARGUMENT;
}
spCameraDeviceCallback_ = callback;
if (spStreamOperator_ == nullptr) {
// Here, an spStreamOperator object is created and passed to the caller for stream operations.
spStreamOperator_ = new(std::nothrow) StreamOperatorImpl(spCameraDeviceCallback_, shared_from_this());
if (spStreamOperator_ == nullptr) {
CAMERA_LOGW("create stream operator failed.");
return DEVICE_ERROR;
}
ismOperator_ = spStreamOperator_;
}
streamOperator = ismOperator_;
spStreamOperator_->SetRequestCallback([this](){
spCameraDeviceCallback_->OnError(REQUEST_TIMEOUT, 0);
});
}
```
Use the **CommitStreams\(\)** method to configure the stream, including PipelineCore initialization and creation. It must be called after the stream is created. 6. Create a stream.
``` Fill in the **StreamInfo** structure before creating a stream by calling **CreateStreams()**.
CamRetCode StreamOperatorImpl::CommitStreams(OperationMode mode, const std::shared_ptr<CameraStandard::CameraMetadata>& modeSetting)
{ ```
auto cameraDevice = cameraDevice_.lock(); using StreamInfo = struct _StreamInfo {
if (cameraDevice == nullptr) { int streamId_;
CAMERA_LOGE("camera device closed."); int width_; // Stream width
return CAMERA_CLOSED; int height_; // Stream height
} int format_; // Stream format, for example, PIXEL_FMT_YCRCB_420_SP
std::shared_ptr<IPipelineCore> PipelineCore = int dataSpace_;
std::static_pointer_cast<CameraDeviceImpl>(cameraDevice)->GetPipelineCore(); StreamIntent intent_; // StreamIntent, for example, PREVIEW
if (PipelineCore == nullptr) { bool tunneledMode_;
OHOS::sptr<OHOS::IBufferProducer> bufferQueue_; // The stream buffer queue can be created by using the streamCustomer->CreateProducer() interface.
int minFrameDuration_;
EncodeType encodeType_;
};
```
The **CreateStreams()** interface in the **StreamOperatorImpl** class is used to create a **StreamBase** instance, which can then be used to initialize operations such as **CreateBufferPool()** by using the **init()** interface.
```
RetCode StreamOperatorImpl::CreateStream(const std::shared_ptr<StreamInfo>& streamInfo)
{
static std::map<StreamIntent, std::string> typeMap = {
{PREVIEW, "PREVIEW"},
{VIDEO, "VIDEO"},
{STILL_CAPTURE, "STILL_CAPTURE"},
{POST_VIEW, "POST_VIEW"}, {ANALYZE, "ANALYZE"},
{CUSTOM, "CUSTOM"}
};
auto itr = typeMap.find(streamInfo->intent_);
if (itr == typeMap.end()) {
CAMERA_LOGE("do not support stream type. [type = %{public}d]", streamInfo->intent_);
return RC_ERROR;
}
std::shared_ptr<StreamBase> stream = StreamFactory::Instance().CreateShared(itr->second); // Create a StreamBase instance.
RetCode rc = stream->Init(streamInfo);
return RC_OK;
}
```
7. Configure the stream.
Use the **CommitStreams()** interface to configure the stream, including PipelineCore initialization and creation. It must be called after the stream is created.
```
CamRetCode StreamOperatorImpl::CommitStreams(OperationMode mode, const std::shared_ptr<CameraStandard::CameraMetadata>& modeSetting)
{
auto cameraDevice = cameraDevice_.lock();
if (cameraDevice == nullptr) {
CAMERA_LOGE("camera device closed.");
return CAMERA_CLOSED;
}
std::shared_ptr<IPipelineCore> PipelineCore =
std::static_pointer_cast<CameraDeviceImpl>(cameraDevice)->GetPipelineCore();
if (PipelineCore == nullptr) {
CAMERA_LOGE("Failed to obtain PipelineCore."); CAMERA_LOGE("Failed to obtain PipelineCore.");
return CAMERA_CLOSED; return CAMERA_CLOSED;
} }
streamPipeCore_ = PipelineCore->GetStreamPipelineCore(); streamPipeCore_ = PipelineCore->GetStreamPipelineCore();
if (streamPipeCore_ == nullptr) { if (streamPipeCore_ == nullptr) {
CAMERA_LOGE("Failed to obtain the stream PipelineCore."); CAMERA_LOGE("Failed to obtain the stream PipelineCore.");
return DEVICE_ERROR; return DEVICE_ERROR;
} }
RetCode rc = streamPipeCore_->Init(); // Initialize the PipelineCore. RetCode rc = streamPipeCore_->Init(); // Initialize the PipelineCore.
if (rc != RC_OK) { if (rc != RC_OK) {
CAMERA_LOGE("Failed to initialize the stream PipelineCore."); CAMERA_LOGE("Failed to initialize the stream PipelineCore.");
return DEVICE_ERROR; return DEVICE_ERROR;
} }
rc = streamPipeCore_->CreatePipeline(mode); // Create a pipeline. rc = streamPipeCore_->CreatePipeline(mode); // Create a pipeline.
if (rc != RC_OK) { if (rc != RC_OK) {
CAMERA_LOGE("Failed to create pipeline."); CAMERA_LOGE("Failed to create pipeline.");
return INVALID_ARGUMENT; return INVALID_ARGUMENT;
} }
return NO_ERROR; return NO_ERROR;
} }
``` ```
8. Capture images. 8. Capture images.
Fill in the **CaptureInfo** structure before calling the **Capture\(\)** method. Fill in the **CaptureInfo** structure before calling the **Capture()** method.
``` ```
using CaptureInfo = struct _CaptureInfo { using CaptureInfo = struct _CaptureInfo {
std::vector<int> streamIds_; // IDs of streams to be captured std::vector<int> streamIds_; // IDs of streams to be captured
std::shared_ptr<CameraStandard::CameraMetadata> captureSetting_; // Camera ability can be obtained through the GetCameraAbility() interface of CameraHost. std::shared_ptr<CameraStandard::CameraMetadata> captureSetting_; // Camera ability can be obtained through the GetCameraAbility() interface of CameraHost.
bool enableShutterCallback_; bool enableShutterCallback_;
}; };
``` ```
Use the **Capture\(\)** interface in **StreamOperatorImpl** to call the **CreateCapture\(\)** interface to capture streams. Use the **Capture()** interface in **StreamOperatorImpl** to call the **CreateCapture()** interface to capture streams.
``` ```
CamRetCode StreamOperatorImpl::Capture(int captureId, const std::shared_ptr<CaptureInfo>& captureInfo, bool isStreaming) CamRetCode StreamOperatorImpl::Capture(int captureId, const std::shared_ptr<CaptureInfo>& captureInfo, bool isStreaming)
{ {
if (!ValidCaptureInfo(captureId, captureInfo)) { if (!ValidCaptureInfo(captureId, captureInfo)) {
CAMERA_LOGE("capture streamIds is empty. [captureId = %d]", captureId); CAMERA_LOGE("capture streamIds is empty. [captureId = %d]", captureId);
return INVALID_ARGUMENT; return INVALID_ARGUMENT;
} }
std::shared_ptr<CameraCapture> cameraCapture = nullptr; std::shared_ptr<CameraCapture> cameraCapture = nullptr;
RetCode rc = CreateCapture(captureId, captureInfo, isStreaming, cameraCapture); RetCode rc = CreateCapture(captureId, captureInfo, isStreaming, cameraCapture);
if (rc != RC_OK) { if (rc != RC_OK) {
CAMERA_LOGE("create capture is failed."); CAMERA_LOGE("create capture is failed.");
return DEVICE_ERROR; return DEVICE_ERROR;
} }
{ {
std::unique_lock<std::mutex> lock(captureMutex_); std::unique_lock<std::mutex> lock(captureMutex_);
camerCaptureMap_.insert(std::make_pair(captureId, cameraCapture)); camerCaptureMap_.insert(std::make_pair(captureId, cameraCapture));
} }
rc = StartThread(); rc = StartThread();
if (rc != RC_OK) { if (rc != RC_OK) {
CAMERA_LOGE("preview start failed."); CAMERA_LOGE("preview start failed.");
return DEVICE_ERROR; return DEVICE_ERROR;
} }
return NO_ERROR; return NO_ERROR;
} }
``` ```
9. Cancel the capture and release the offline stream. 9. Cancel the capture and release the offline stream.
Use the **CancelCapture\(\)** interface in the **StreamOperatorImpl** class to cancel the stream capture based on **captureId**. Use the **CancelCapture()** interface in the **StreamOperatorImpl** class to cancel the stream capture based on **captureId**.
``` ```
CamRetCode StreamOperatorImpl::CancelCapture(int captureId) CamRetCode StreamOperatorImpl::CancelCapture(int captureId)
{ {
auto itr = camerCaptureMap_.find(captureId); // Search for the CameraCapture object in the Map based on the captureId. auto itr = camerCaptureMap_.find(captureId); // Search for the CameraCapture object in the Map based on the captureId.
RetCode rc = itr->second->Cancel(); // Call the Cancel() interface in CameraCapture to cancel the stream capture. RetCode rc = itr->second->Cancel(); // Call the Cancel() interface in CameraCapture to cancel the stream capture.
std::unique_lock<std::mutex> lock(captureMutex_); std::unique_lock<std::mutex> lock(captureMutex_);
camerCaptureMap_.erase(itr); // Erase the CameraCapture object. camerCaptureMap_.erase(itr); // Erase the CameraCapture object.
return NO_ERROR; return NO_ERROR;
} }
``` ```
Use the **ReleaseStreams\(\)** interface in the **StreamOperatorImpl** class t release the streams created by using **CreateStream\(\)** and **CommitStreams\(\)** and destroy the pipeline. Use the **ReleaseStreams()** interface in the **StreamOperatorImpl** class t release the streams created by using **CreateStream()** and **CommitStreams()** and destroy the pipeline.
``` ```
CamRetCode StreamOperatorImpl::ReleaseStreams(const std::vector<int>& streamIds) CamRetCode StreamOperatorImpl::ReleaseStreams(const std::vector<int>& streamIds)
{ {
RetCode rc = DestroyStreamPipeline(streamIds); // Destroy the pipeline based on streamIds. RetCode rc = DestroyStreamPipeline(streamIds); // Destroy the pipeline based on streamIds.
rc = DestroyHostStreamMgr(streamIds); rc = DestroyHostStreamMgr(streamIds);
rc = DestroyStreams(streamIds); // Destroy the stream specified by streamIds. rc = DestroyStreams(streamIds); // Destroy the stream specified by streamIds.
return NO_ERROR; return NO_ERROR;
} }
``` ```
10. Close the camera device. 10. Close the camera device.
Use the **Close\(\)** interface in the **CameraDeviceImpl** class to close the camera device. This interface calls **PowerDown\(\)** in the **DeviceManager** to power off the device.
## Development Example
There is a camera demo in the **/drivers/peripheral/camera/hal/init** directory. After system startup, the executable file **ohos\_camera\_demo** is generated in the **/system/bin** directory. This demo can implement basic camera capabilities such as preview and photographing. The following uses the demo as an example to describe how to use the HDI to implement the **PreviewOn\(\)** and **CaptureON\(\)** interfaces.
1. Construct a Hos3516Demo object in the **main** function. This object contains methods for initializing the camera and starting, stopping, and releasing streams. The **mainDemo-\>InitSensors\(\)** function is used to initialize the **CameraHost**, and the **mainDemo-\>InitCameraDevice\(\)** function is used to initialize the **CameraDevice**.
```
int main(int argc, char** argv)
{
RetCode rc = RC_OK;
auto mainDemo = std::make_shared<Hos3516Demo>();
rc = mainDemo->InitSensors(); // Initialize the CameraHost.
if (rc == RC_ERROR) {
CAMERA_LOGE("main test: mainDemo->InitSensors() error\n");
return -1;
}
rc = mainDemo->InitCameraDevice(); // Initialize the CameraDevice.
if (rc == RC_ERROR) {
CAMERA_LOGE("main test: mainDemo->InitCameraDevice() error\n");
return -1;
}
rc = PreviewOn(0, mainDemo); // Configure and enable streams.
if (rc != RC_OK) {
CAMERA_LOGE("main test: PreviewOn() error demo exit");
return -1;
}
ManuList(mainDemo, argc, argv); // Print the menu to the console.
return RC_OK;
}
```
The function used to initialize the **CameraHost** is implemented as follows, where the HDI **ICameraHost::Get\(\)** is called to obtain the **demoCameraHost** and set the callback:
```
RetCode Hos3516Demo::InitSensors()
{
demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME);
if (demoCameraHost_ == nullptr) {
CAMERA_LOGE("demo test: ICameraHost::Get error");
return RC_ERROR;
}
hostCallback_ = new CameraHostCallback();
rc = demoCameraHost_->SetCallback(hostCallback_);
return RC_OK;
}
```
The implementation of the function for initializing the **CameraDevice** is as follows, where the **GetCameraIds\(cameraIds\_\)**, **GetCameraAbility\(cameraId, ability\_\)**, and **OpenCamera\(cameraIds\_.front\(\), callback, demoCameraDevice\_\)** interfaces are called to obtain the **demoCameraHost**.
```
RetCode Hos3516Demo::InitCameraDevice()
{
(void)demoCameraHost_->GetCameraIds(cameraIds_);
const std::string cameraId = cameraIds_.front();
demoCameraHost_->GetCameraAbility(cameraId, ability_);
sptr<CameraDeviceCallback> callback = new CameraDeviceCallback();
rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_);
return RC_OK;
}
```
2. Implement the **PreviewOn\(\)** interface to configure streams, enable preview streams, and start stream capture. After this interface is called, the camera preview channel starts running. Two streams are enabled: preview stream and capture or video stream. Only the preview stream will be captured.
```
static RetCode PreviewOn(int mode, const std::shared_ptr<Hos3516Demo>& mainDemo)
{
rc = mainDemo->StartPreviewStream(); // Configure the preview stream.
if (mode == 0) {
rc = mainDemo->StartCaptureStream(); // Configure the capture stream.
} else {
rc = mainDemo->StartVideoStream(); // Configure the video stream.
}
rc = mainDemo->CaptureON(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW); // Capture the preview stream.
return RC_OK;
}
```
The **StartCaptureStream\(\)**, **StartVideoStream\(\)**, and **StartPreviewStream\(\)** interfaces call the **CreateStream\(\)** interface with different input parameters.
```
RetCode Hos3516Demo::StartVideoStream()
{
RetCode rc = RC_OK;
if (isVideoOn_ == 0) {
isVideoOn_ = 1;
rc = CreateStream(STREAM_ID_VIDEO, streamCustomerVideo_, VIDEO); // To enable the preview stream or capture stream, change the input parameters.
}
return RC_OK;
}
```
The **CreateStream\(\)** interface calls the HDI to configure and create a stream. Specifically, the interface first calls the HDI to obtain a **StreamOperation** object and then creates a **StreamInfo** object. Call **CreateStreams\(\)** and **CommitStreams\(\)** to create and configure a stream.
```
RetCode Hos3516Demo::CreateStreams(const int streamIdSecond, StreamIntent intent)
{
std::vector<std::shared_ptr<StreamInfo>> streamInfos;
std::vector<std::shared_ptr<StreamInfo>>().swap(streamInfos);
GetStreamOpt(); // Obtain a StreamOperator object.
std::shared_ptr<StreamInfo> previewStreamInfo = std::make_shared<StreamInfo>();
SetStreamInfo(previewStreamInfo, streamCustomerPreview_, STREAM_ID_PREVIEW, PREVIEW); // Fill in the StreamInfo.
if (previewStreamInfo->bufferQueue_ == nullptr) {
CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n");
return RC_ERROR;
}
streamInfos.push_back(previewStreamInfo);
std::shared_ptr<StreamInfo> secondStreamInfo = std::make_shared<StreamInfo>();
if (streamIdSecond == STREAM_ID_CAPTURE) {
SetStreamInfo(secondStreamInfo, streamCustomerCapture_, STREAM_ID_CAPTURE, intent);
} else {
SetStreamInfo(secondStreamInfo, streamCustomerVideo_, STREAM_ID_VIDEO, intent);
}
if (secondStreamInfo->bufferQueue_ == nullptr) { Use the **Close()** interface in the **CameraDeviceImpl** class to close the camera device. This interface calls **PowerDown()** in the **DeviceManager** to power off the device.
CAMERA_LOGE("demo test: CreateStreams CreateProducer() secondStreamInfo is nullptr\n");
return RC_ERROR; ### Development Example<a name = "8"></a>
}
streamInfos.push_back(secondStreamInfo); There is a camera demo in the **/drivers/peripheral/camera/hal/init** directory. After system startup, the executable file **ohos_camera_demo** is generated in the **/vendor/bin** directory. This demo can implement basic camera capabilities such as preview and photographing. The following uses the demo as an example to describe how to use the HDI to write the **PreviewOn()** and **CaptureON()** instances. For details, see [ohos_camera_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/hal/init).
rc = streamOperator_->CreateStreams(streamInfos); // Create a stream. 1. Construct a CameraDemo object in the **main** function. This object contains methods for initializing the camera and starting, stopping, and releasing streams. The **mainDemo->InitSensors()** function is used to initialize the **CameraHost**, and the **mainDemo->InitCameraDevice()** function is used to initialize the **CameraDevice**.
if (rc != Camera::NO_ERROR) {
CAMERA_LOGE("demo test: CreateStream CreateStreams error\n"); ```
return RC_ERROR; int main(int argc, char** argv)
} {
RetCode rc = RC_OK;
rc = streamOperator_->CommitStreams(Camera::NORMAL, ability_); // Commit the stream. auto mainDemo = std::make_shared<CameraDemo>();
if (rc != Camera::NO_ERROR) { rc = mainDemo->InitSensors(); // Initialize the CameraHost.
CAMERA_LOGE("demo test: CreateStream CommitStreams error\n"); if (rc == RC_ERROR) {
std::vector<int> streamIds = {STREAM_ID_PREVIEW, streamIdSecond}; CAMERA_LOGE("main test: mainDemo->InitSensors() error\n");
streamOperator_->ReleaseStreams(streamIds); return -1;
return RC_ERROR; }
}
return RC_OK; rc = mainDemo->InitCameraDevice(); // Initialize the CameraDevice.
} if (rc == RC_ERROR) {
``` CAMERA_LOGE("main test: mainDemo->InitCameraDevice() error\n");
return -1;
The **CaptureON\(\)** interface calls the **Capture\(\)** method of **StreamOperator** to obtain camera data, rotate the buffer, and start a thread to receive data of the corresponding type. }
``` rc = PreviewOn(0, mainDemo); // Configure and enable streams.
RetCode Hos3516Demo::CaptureON(const int streamId, const int captureId, CaptureMode mode) if (rc != RC_OK) {
{ CAMERA_LOGE("main test: PreviewOn() error demo exit");
The std::shared_ptr<Camera::CaptureInfo> captureInfo = std::make_shared<Camera::CaptureInfo>(); // Create and fill in CaptureInfo. return -1;
captureInfo->streamIds_ = {streamId}; }
captureInfo->captureSetting_ = ability_;
captureInfo->enableShutterCallback_ = false; ManuList(mainDemo, argc, argv); // Print the menu to the console.
The int rc = streamOperator_->Capture(captureId, captureInfo, true); // The stream capture starts, and buffer recycling starts. return RC_OK;
if (mode == CAPTURE_PREVIEW) { }
streamCustomerPreview_->ReceiveFrameOn(nullptr); // Create a preview thread to receive the passed buffers. ```
} else if (mode == CAPTURE_SNAPSHOT) {
The streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a capture thread to receive the passed buffers through the StoreImage callback. The function used to initialize the **CameraHost** is implemented as follows, where the HDI **ICameraHost::Get()** is called to obtain the **demoCameraHost** and set the callback:
StoreImage(addr, size);
}); ```
} else if (mode == CAPTURE_VIDEO) { RetCode CameraDemo::InitSensors()
OpenVideoFile(); {
streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) {// Create a video thread to receive the passed buffer by calling the StoreVideo callback. demoCameraHost_ = ICameraHost::Get(DEMO_SERVICE_NAME);
StoreVideo(addr, size); if (demoCameraHost_ == nullptr) {
}); CAMERA_LOGE("demo test: ICameraHost::Get error");
} return RC_ERROR;
return RC_OK; }
}
``` hostCallback_ = new CameraHostCallback();
rc = demoCameraHost_->SetCallback(hostCallback_);
3. Implement the **ManuList\(\)** function to obtain characters from the console through the **fgets\(\)** interface. Different characters correspond to different capabilities provided by the demo, and the functionality menu is printed. return RC_OK;
}
``` ```
static void ManuList(const std::shared_ptr<Hos3516Demo>& mainDemo,
const int argc, char** argv) The implementation of the function for initializing the **CameraDevice** is as follows, where the **GetCameraIds(cameraIds_)**, **GetCameraAbility(cameraId, ability_)**, and **OpenCamera(cameraIds_.front(), callback, demoCameraDevice_)** interfaces are called to obtain the **demoCameraHost**.
{
int idx, c; ```
int awb = 1; RetCode CameraDemo::InitCameraDevice()
constexpr char shortOptions[] = "h:cwvaqof:"; {
c = getopt_long(argc, argv, shortOptions, longOptions, &idx); (void)demoCameraHost_->GetCameraIds(cameraIds_);
while(1) { const std::string cameraId = cameraIds_.front();
switch (c) { demoCameraHost_->GetCameraAbility(cameraId, ability_);
case 'h':
c = PutMenuAndGetChr(); // Print the menu. sptr<CameraDeviceCallback> callback = new CameraDeviceCallback();
break; rc = demoCameraHost_->OpenCamera(cameraIds_.front(), callback, demoCameraDevice_);
return RC_OK;
case 'f': }
FlashLightTest(mainDemo); // Test the flashlight capability. ```
c = PutMenuAndGetChr();
break; 2. Implement the **PreviewOn()** interface to configure streams, enable preview streams, and start stream capture. After this interface is called, the camera preview channel starts running. Two streams are enabled: preview stream and capture or video stream. Only the preview stream will be captured.
case 'o':
OfflineTest(mainDemo); // Test the offline capability. ```
c = PutMenuAndGetChr(); static RetCode PreviewOn(int mode, const std::shared_ptr<CameraDemo>& mainDemo)
break; {
case 'c': rc = mainDemo->StartPreviewStream(); // Configure the preview stream.
CaptureTest(mainDemo); // Test the capture capability. if (mode == 0) {
c = PutMenuAndGetChr(); rc = mainDemo->StartCaptureStream(); // Configure the capture stream.
break; } else {
case 'w': // Test the AWB capability. rc = mainDemo->StartVideoStream(); // Configure the video stream.
if (awb) { }
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT);
} else { rc = mainDemo->CaptureON(STREAM_ID_PREVIEW, CAPTURE_ID_PREVIEW, CAPTURE_PREVIEW); // Capture the preview stream.
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF); return RC_OK;
} }
awb = !awb; ```
c = PutMenuAndGetChr();
break; The **StartCaptureStream()**, **StartVideoStream()**, and **StartPreviewStream()** interfaces call the **CreateStream()** interface with different input parameters.
case 'a': // Test the AE capability.
mainDemo->SetAeExpo(); ```
c = PutMenuAndGetChr(); RetCode CameraDemo::StartVideoStream()
break; {
case 'v': // Test the video capability. RetCode rc = RC_OK;
VideoTest(mainDemo); if (isVideoOn_ == 0) {
c = PutMenuAndGetChr(); isVideoOn_ = 1;
break; rc = CreateStream(STREAM_ID_VIDEO, streamCustomerVideo_, VIDEO); // To enable the preview stream or capture stream, change the input parameters.
case 'q': // Exit the demo. }
PreviewOff(mainDemo); return RC_OK;
mainDemo->QuitDemo(); }
exit(EXIT_SUCCESS); ```
default: The **CreateStream()** interface calls the HDI to configure and create a stream. Specifically, the interface first calls the HDI to obtain a **StreamOperation** object and then creates a **StreamInfo** object. Call **CreateStreams()** and **CommitStreams()** to create and configure a stream.
CAMERA_LOGE("main test: command error please retry input command");
c = PutMenuAndGetChr(); ```
break; RetCode CameraDemo::CreateStreams(const int streamIdSecond, StreamIntent intent)
} {
} std::vector<std::shared_ptr<StreamInfo>> streamInfos;
} std::vector<std::shared_ptr<StreamInfo>>().swap(streamInfos);
``` GetStreamOpt(); // Obtain a StreamOperator object.
std::shared_ptr<StreamInfo> previewStreamInfo = std::make_shared<StreamInfo>();
The **PutMenuAndGetChr\(\)** interface prints the menu of the demo and calls **fgets\(\)** to wait for commands from the console. SetStreamInfo(previewStreamInfo, streamCustomerPreview_, STREAM_ID_PREVIEW, PREVIEW); // Fill in the StreamInfo.
if (previewStreamInfo->bufferQueue_ == nullptr) {
``` CAMERA_LOGE("demo test: CreateStream CreateProducer(); is nullptr\n");
static int PutMenuAndGetChr(void) return RC_ERROR;
{ }
constexpr uint32_t inputCount = 50; streamInfos.push_back(previewStreamInfo);
int c = 0;
char strs[inputCount]; std::shared_ptr<StreamInfo> secondStreamInfo = std::make_shared<StreamInfo>();
Usage(stdout); if (streamIdSecond == STREAM_ID_CAPTURE) {
CAMERA_LOGD("pls input command(input -q exit this app)\n"); SetStreamInfo(secondStreamInfo, streamCustomerCapture_, STREAM_ID_CAPTURE, intent);
fgets(strs, inputCount, stdin); } else {
SetStreamInfo(secondStreamInfo, streamCustomerVideo_, STREAM_ID_VIDEO, intent);
for (int i = 0; i < inputCount; i++) { }
if (strs[i] != '-') {
c = strs[i]; if (secondStreamInfo->bufferQueue_ == nullptr) {
break; CAMERA_LOGE("demo test: CreateStreams CreateProducer() secondStreamInfo is nullptr\n");
} return RC_ERROR;
} }
return c; streamInfos.push_back(secondStreamInfo);
}
``` rc = streamOperator_->CreateStreams(streamInfos); // Create a stream.
if (rc != Camera::NO_ERROR) {
The console outputs the menu details as follows: CAMERA_LOGE("demo test: CreateStream CreateStreams error\n");
return RC_ERROR;
``` }
"Options:\n"
"-h | --help Print this message\n" rc = streamOperator_->CommitStreams(Camera::NORMAL, ability_);
"-o | --offline stream offline test\n" if (rc != Camera::NO_ERROR) {
"-c | --capture capture one picture\n" CAMERA_LOGE("demo test: CreateStream CommitStreams error\n");
"-w | --set WB Set white balance Cloudy\n" std::vector<int> streamIds = {STREAM_ID_PREVIEW, streamIdSecond};
"-v | --video capture Viedeo of 10s\n" streamOperator_->ReleaseStreams(streamIds);
"-a | --Set AE Set Auto exposure\n" return RC_ERROR;
"-f | --Set Flashlight Set flashlight ON 5s OFF\n" }
"-q | --quit stop preview and quit this app\n"); return RC_OK;
``` }
```
Other capabilities in the demo are implemented by calling different HDIs, which are similar to **PreviewOn\(\)**. For details, see [ohos\_camera\_demo](https://gitee.com/openharmony/drivers_peripheral/tree/master/camera/hal/init).
The **CaptureON()** interface calls the **Capture()** interface of **StreamOperator** to obtain camera data, rotate the buffer, and start a thread to receive data of the corresponding type.
```
RetCode CameraDemo::CaptureON(const int streamId, const int captureId, CaptureMode mode)
{
std::shared_ptr<Camera::CaptureInfo> captureInfo = std::make_shared<Camera::CaptureInfo>(); // Create and fill in CaptureInfo.
captureInfo->streamIds_ = {streamId};
captureInfo->captureSetting_ = ability_;
captureInfo->enableShutterCallback_ = false;
int rc = streamOperator_->Capture(captureId, captureInfo, true);// The stream capture starts, and buffer recycling starts.
if (mode == CAPTURE_PREVIEW) {
streamCustomerPreview_->ReceiveFrameOn(nullptr); // Create a preview thread to receive the passed buffers.
} else if (mode == CAPTURE_SNAPSHOT) {
streamCustomerCapture_->ReceiveFrameOn([this](void* addr, const uint32_t size) { // Create a capture thread to receive the passed buffers through the StoreImage callback.
StoreImage(addr, size);
});
} else if (mode == CAPTURE_VIDEO) {
OpenVideoFile();
streamCustomerVideo_->ReceiveFrameOn([this](void* addr, const uint32_t size) {// Create a video thread to receive the passed buffer by calling the StoreVideo callback.
StoreVideo(addr, size);
});
}
return RC_OK;
}
```
3. Implement the **ManuList()** function to obtain characters from the console through the **fgets()** interface. Different characters correspond to different capabilities provided by the demo, and the functionality menu is printed.
```
static void ManuList(const std::shared_ptr<CameraDemo>& mainDemo,
const int argc, char** argv)
{
int idx, c;
int awb = 1;
constexpr char shortOptions[] = "h:cwvaqof:";
c = getopt_long(argc, argv, shortOptions, longOptions, &idx);
while(1) {
switch (c) {
case 'h':
c = PutMenuAndGetChr(); // Print the menu.
break;
case 'f':
FlashLightTest(mainDemo); // Test the flashlight capability.
c = PutMenuAndGetChr();
break;
case 'o':
OfflineTest(mainDemo); // Test the offline capability.
c = PutMenuAndGetChr();
break;
case 'c':
CaptureTest(mainDemo); // Test the capture capability.
c = PutMenuAndGetChr();
break;
case 'w': // Test the AWB capability.
if (awb) {
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_INCANDESCENT);
} else {
mainDemo->SetAwbMode(OHOS_CAMERA_AWB_MODE_OFF);
}
awb = !awb;
c = PutMenuAndGetChr();
break;
case 'a': // Test the AE capability.
mainDemo->SetAeExpo();
c = PutMenuAndGetChr();
break;
case 'v': // Test the video capability.
VideoTest(mainDemo);
c = PutMenuAndGetChr();
break;
case 'q': // Exit the demo.
PreviewOff(mainDemo);
mainDemo->QuitDemo();
exit(EXIT_SUCCESS);
default:
CAMERA_LOGE("main test: command error please retry input command");
c = PutMenuAndGetChr();
break;
}
}
}
```
The **PutMenuAndGetChr()** interface prints the menu of the demo and calls **fgets()** to wait for commands from the console.
```
static int PutMenuAndGetChr(void)
{
constexpr uint32_t inputCount = 50;
int c = 0;
char strs[inputCount];
Usage(stdout);
CAMERA_LOGD("pls input command(input -q exit this app)\n");
fgets(strs, inputCount, stdin);
for (int i = 0; i < inputCount; i++) {
if (strs[i] != '-') {
c = strs[i];
break;
}
}
return c;
}
```
The console outputs the menu details as follows:
```
"Options:\n"
"-h | --help Print this message\n"
"-o | --offline stream offline test\n"
"-c | --capture capture one picture\n"
"-w | --set WB Set white balance Cloudy\n"
"-v | --video capture Viedeo of 10s\n"
"-a | --Set AE Set Auto exposure\n"
"-f | --Set Flashlight Set flashlight ON 5s OFF\n"
"-q | --quit stop preview and quit this app\n");
```
...@@ -159,9 +159,9 @@ The following example shows code for developing an LCD driver: ...@@ -159,9 +159,9 @@ The following example shows code for developing an LCD driver:
#define HORIZONTAL_BACK_PORCH 20 #define HORIZONTAL_BACK_PORCH 20
#define HORIZONTAL_FRONT_PORCH 20 #define HORIZONTAL_FRONT_PORCH 20
#define HORIZONTAL_SYNC_WIDTH 10 #define HORIZONTAL_SYNC_WIDTH 10
#define VERTIACL_BACK_PORCH 14 #define VERTICAL_BACK_PORCH 14
#define VERTIACL_FRONT_PORCH 16 #define VERTICAL_FRONT_PORCH 16
#define VERTIACL_SYNC_WIDTH 2 #define VERTICAL_SYNC_WIDTH 2
#define FRAME_RATE 60 #define FRAME_RATE 60
/* PanelInfo structure */ /* PanelInfo structure */
...@@ -300,9 +300,9 @@ static struct PanelInfo g_panelInfo = { ...@@ -300,9 +300,9 @@ static struct PanelInfo g_panelInfo = {
.hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */
.hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */
.hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */
.vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ .vbp = VERTICAL_BACK_PORCH, /* vertical back porch */
.vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ .vfp = VERTICAL_FRONT_PORCH, /* vertical front porch */
.vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ .vsw = VERTICAL_SYNC_WIDTH, /* vertical sync width */
.frameRate = FRAME_RATE, /* frame rate */ .frameRate = FRAME_RATE, /* frame rate */
.intfType = MIPI_DSI, /* panel interface type */ .intfType = MIPI_DSI, /* panel interface type */
.intfSync = OUTPUT_USER, /* output timming type */ .intfSync = OUTPUT_USER, /* output timming type */
......
...@@ -148,7 +148,7 @@ The light driver model provides APIs to obtain information about all the lights ...@@ -148,7 +148,7 @@ The light driver model provides APIs to obtain information about all the lights
HdfWorkDestroy(&drvData->work); HdfWorkDestroy(&drvData->work);
HdfWorkQueueDestroy(&drvData->workQueue); HdfWorkQueueDestroy(&drvData->workQueue);
(void)OsalMutexDestroy(&drvData->mutex); (void)OsalMutexDestroy(&drvData->mutex);
(void)OsalMemFree(drvData); OsalMemFree(drvData);
g_lightDrvData = NULL; g_lightDrvData = NULL;
} }
``` ```
......
# Sensor # Sensor
## Overview ## Overview
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
The sensor driver model masks the sensor hardware differences and provides interfaces for the upper-layer sensor service to implement basic sensor capabilities, including querying the sensor list, enabling or disabling a sensor, subscribing to or unsubscribing from sensor data changes, and setting sensor options. The model is developed on the Hardware Driver Foundation (HDF), Operating System Abstraction Layer (OSAL), and platform driver interfaces (such as the I2C, SPI, and UART buses). It provides functionalities such as cross-OS migration and differentiated device configurations. The figure below shows the architecture of the sensor driver model. The sensor driver model masks the sensor hardware differences and provides interfaces for the upper-layer sensor service to implement basic sensor capabilities, including querying the sensor list, enabling or disabling a sensor, subscribing to or unsubscribing from sensor data changes, and setting sensor options. The model is developed on the Hardware Driver Foundation (HDF), Operating System Abstraction Layer (OSAL), and platform driver interfaces (such as the I2C, SPI, and UART buses). It provides functionalities such as cross-OS migration and differentiated device configurations. The figure below shows the architecture of the sensor driver model.
**Figure 1** Sensor driver model **Figure 1** Sensor driver model
![Sensor driver model](figures/sensor_driver_model.png) ![Sensor driver model](figures/sensor_driver_model.png)
### Basic Concepts ### Basic Concepts
...@@ -44,12 +45,12 @@ The following uses the acceleration sensor driver on the Hi3516D V300 developmen ...@@ -44,12 +45,12 @@ The following uses the acceleration sensor driver on the Hi3516D V300 developmen
### When to Use ### When to Use
- Data provided by the gravity and gyroscope sensors denotes the tilt and rotation of the device, which helps your application improve user experience in games. - Data provided by the gravity and gyroscope sensors denotes the tilt and rotation of the device, which helps your application improve user experience in games.
- Data provided by the proximity sensor denotes the distance between the device and a visible object, which enables the device to automatically turn on or off its screen accordingly to prevent accidental touch on the screen. For example, when the proximity sensor detects the user face approaches the earpiece during a call, it triggers backlight of the screen to be turned off. This can further reduce power consumption. - Data provided by the proximity sensor denotes the distance between the device and a visible object, which enables the device to automatically turn on or off its screen accordingly to prevent accidental touch on the screen. For example, when the proximity sensor detects the user face approaches the earpiece during a call, it triggers backlight of the screen to be turned off. This prevents the screen from being accidentally touched and further reduces power consumption.
- Data provided by the barometric pressure sensor helps your application accurately determine the altitude of the device. - Data provided by the barometric pressure sensor helps your application accurately determine the altitude of the device.
- Data provided by the ambient light sensor helps your device automatically adjust its backlight. - Data provided by the ambient light sensor helps your device automatically adjust its backlight.
- Data provided by the Hall effect sensor implements the smart cover mode of your device. When the smart cover is closed, a small window is opened on the phone to reduce power consumption. - Data provided by the Hall effect sensor implements the smart cover mode of your device. When the smart cover is closed, a small window is opened on the phone to reduce power consumption.
### Available APIs<a name="section188213414114"></a> ### Available APIs
The sensor driver model offers the following APIs: The sensor driver model offers the following APIs:
...@@ -61,7 +62,7 @@ The sensor driver model offers the following APIs: ...@@ -61,7 +62,7 @@ The sensor driver model offers the following APIs:
The sensor driver model provides APIs for the hardware service to make sensor service development easier. See the table below. The sensor driver model provides APIs for the hardware service to make sensor service development easier. See the table below.
**Table 1** APIs for the members in the PinCntlrMethod structure **Table 1** APIs of the sensor driver model
| API| Description| | API| Description|
| ----- | -------- | | ----- | -------- |
...@@ -111,9 +112,9 @@ The sensor driver model also provides certain driver development APIs that need ...@@ -111,9 +112,9 @@ The sensor driver model also provides certain driver development APIs that need
| void ReadSensorData(void) | Reads sensor data.| | void ReadSensorData(void) | Reads sensor data.|
For details about the interface implementation, see [How to Develop](#section7893102915819). For details about the interface implementation, see "How to Develop" below.
### How to Develop<a name="section7893102915819"></a> ### How to Develop
1. Develop the acceleration sensor abstract driver. Specifically, implement the **Bind**, **Init**, **Release**, and **Dispatch** functions. 1. Develop the acceleration sensor abstract driver. Specifically, implement the **Bind**, **Init**, **Release**, and **Dispatch** functions.
- Implement the entry function for the acceleration sensor. - Implement the entry function for the acceleration sensor.
...@@ -513,12 +514,11 @@ For details about the interface implementation, see [How to Develop](#section789 ...@@ -513,12 +514,11 @@ For details about the interface implementation, see [How to Develop](#section789
>![](../public_sys-resources/icon-note.gif) **NOTE** >![](../public_sys-resources/icon-note.gif) **NOTE**
> >
>- The sensor driver model provides certain APIs to implement sensor driver capabilities, including the driver device management, abstract bus and platform operation, common configuration, and configuration parsing capabilities. For details about them, see [Table 2](#table1156812588320). >- The sensor driver model provides certain APIs to implement sensor driver capabilities, including the driver device management, abstract bus and platform operation, common configuration, and configuration parsing capabilities. For details about them, see Table 2.
> >- You need to implement the following functions: certain sensor operation interfaces (listed in Table 3) and sensor chipset HCS configuration.
>- You need to implement the following functions: certain sensor operation interfaces (listed in [Table 3](#table1083014911336)) and sensor chipset HCS configuration. >- You also need to verify basic driver functions.
> - You also need to verify basic driver functions.
### Commissioning and Verifying<a name="section106021256121219"></a> ### How to Verify
After the driver is developed, you can develop self-test cases in the sensor unit test to verify the basic functions of the driver. Use the developer self-test platform as the test environment. After the driver is developed, you can develop self-test cases in the sensor unit test to verify the basic functions of the driver. Use the developer self-test platform as the test environment.
...@@ -545,7 +545,7 @@ void HdfSensorTest::SetUpTestCase() ...@@ -545,7 +545,7 @@ void HdfSensorTest::SetUpTestCase()
{ {
g_sensorDev = NewSensorInterfaceInstance(); g_sensorDev = NewSensorInterfaceInstance();
if (g_sensorDev == nullptr) { if (g_sensorDev == nullptr) {
printf("test sensorHdi get Module instace failed\n\r"); printf("test sensorHdi get Module instance failed\n\r");
} }
} }
/* Release case resources. */ /* Release case resources. */
......
# DAC
## Overview
### DAC
A digit-to-analog converter (DAC) is a device that converts a digital signal into an analog signal in electronics.
The DAC APIs provide a set of methods for DAC data transfer, including:
- Opening or closing a DAC device
- Setting the target digital-to-analog (DA) value
### Basic Concepts
The DAC module provides the output channel for the process control computer system. It connects to the executor to implement automatic control of the production process. It is also an important module in the analog-to-digital converter using feedback technologies.
- Resolution
The number of binary bits that can be converted by a DAC. A greater number of bits indicates a higher resolution.
- Conversion precision
Difference between the actual output value of the DAC and the theoretical value when the maximum value is added to the input end. The conversion precision of a DAC converter varies depending on the structure of the chip integrated on the DAC and the interface circuit configuration. The ideal conversion precision value should be as small as possible. To achieve optimal DAC conversion precision, the DAC must have high resolution. In addition, errors in the devices or power supply of the interface circuits will affect the conversion precision. When the error exceeds a certain degree, a DAC conversion error will be caused.
- Conversion speed
The conversion speed is determined by the setup time. The setup time is the period from the time the input suddenly changes from all 0s to all 1s to the time the output voltage remains within the FSR ± ½LSB (or FSR ± x%FSR). It is the maximum response time of the DAC, and hence used to measure the conversion speed.
The full scale range (FSR) is the maximum range of the output signal amplitude of a DAC. Different DACs have different FSRs, which can be limited by positive and negative currents or voltages.
The least significant byte (LSB) refers to bit 0 (the least significant bit) in a binary number.
### Working Principles
In the Hardware Driver Foundation (HDF), the DAC module uses the unified service mode for API adaptation. In this mode, a device service is used as the DAC manager to handle access requests from the devices of the same type in a unified manner. The unified service mode applies to the scenario where there are many device objects of the same type. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. The figure below shows the unified service mode.
The DAC module is divided into the following layers:
- The interface layer provides APIs for opening or closing a device and writing data.
- The core layer provides the capabilities of binding, initializing, and releasing devices.
- The adaptation layer implements other functions.
![](../public_sys-resources/icon-note.gif)NOTE<br/>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer.
**Figure 1** Unified service mode
![](figures/unified-service-mode.png "DAC-unified-service-mode")
### Constraints
Currently, the DAC module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
The DAC module converts digital signals into analog signals in the form of current, voltage, or charge. It is mainly used in audio devices. Audio players and headsets use the DAC module as the digital-to-analog conversion channels.
### Available APIs
The table below describes the APIs of the DAC module. For more details, see API Reference.
**Table 1** DAC driver APIs
| API | Description |
| :------------------------------------------------------------| :------------ |
| DevHandle DacOpen(uint32_t number) | Opens a DAC device. |
| void DacClose(DevHandle handle) | Closes a DAC device. |
| int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val) | Sets the target DA value. |
### How to Develop
The figure below illustrates the process of using a DAC device.
**Figure 2** Process of using a DAC device
![](figures/process-of-using-DAC.png "Process of using a DAC")
#### Opening a DAC Device
Call **DacOpen()** to open a DAC device before performing the DA conversion.
```
DevHandle DacOpen(uint32_t number);
```
**Table 2** Description of DacOpen
| **Parameter** | Description |
| ---------- | ----------------- |
| number | DAC device number. |
| **Return Value**| **Description** |
| NULL | Failed to open the DAC device. |
| Device handle | Handle of the DAC device opened.|
Open device 1 of the two ADC devices (numbered 0 and 1) in the system.
```
DevHandle dacHandle = NULL; /* DAC device handle /
/* Open the DAC device. */
dacHandle = DacOpen(1);
if (dacHandle == NULL) {
HDF_LOGE("DacOpen: failed\n");
return;
}
```
#### Setting the Target DA Value
```
int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val);
```
**Table 3** Description of DacWrite
| **Parameter** | Description |
| ---------- | -------------- |
| handle | DAC device handle. |
| channel | DAC channel number. |
| val | DA value to set. |
| **Return Value**| **Description**|
| 0 | The operation is successful. |
| Negative value | The operation failed. |
```
/* Write the target DA value through the DAC_CHANNEL_NUM channel. */
ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret);
DacClose(dacHandle);
return -1;
}
```
#### Closing a DAC Device
After the DAC communication is complete, call **DacClose()** to close the DAC device.
```
void DacClose(DevHandle handle);
```
**Table 4** Description of DacClose
| **Parameter** | Description |
| ---------- | -------------- |
| handle | DAC device handle. |
| **Return Value**| **Description**|
| void | - |
Example:
```
DacClose(dacHandle); /* Close the DAC device. */
```
## Development Example
The procedure is as follows:
1. Open the DAC device based on the device number and obtain the device handle.
2. Set the DA value. If the operation fails, close the device handle.
3. Close the DAC device handle if the access to the DAC is complete.
You can obtain the operation result by printing the log information based on the **val**.
```
#include "hdmi_if.h" /* Header file for DAC APIs */
#include "hdf_log.h" /* Header file for log APIs */
/* Define device 0, channel 1. */
#define DAC_DEVICE_NUM 0
#define DAC_CHANNEL_NUM 1
/* Main entry of DAC routines. */
static int32_t TestCaseDac(void)
{
// Set the target DA value.
uint32_t val = 2;
int32_t ret;
DevHandle dacHandle;
/* Open the DAC device. */
dacHandle = DacOpen(DAC_DEVICE_NUM);
if (dacHandle == NULL) {
HDF_LOGE("%s: Open DAC%u fail!", __func__, DAC_DEVICE_NUM);
return -1;
}
/* Write data. */
ret = DacWrite(dacHandle, DAC_CHANNEL_NUM, val);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: tp DAC write reg fail!:%d", __func__, ret);
DacClose(dacHandle);
return -1;
}
/* Close the DAC device. */
DacClose(dacHandle);
return 0;
}
```
# DAC
## Overview<a name="1"></a>
### DAC<a name="2"></a>
A digit-to-analog converter (DAC) is a device that converts a digital signal into an analog signal in electronics.
### Basic Concepts<a name="3"></a>
The DAC module supports development of digital-to-analog conversion. The DAC module provides the output channel for the process control computer system. It connects to the executor to implement automatic control of the production process. It is also an important module in the analog-to-digital converter using feedback technologies.
- Resolution
The number of binary bits that can be converted by a DAC. A greater number of bits indicates a higher resolution.
- Conversion precision
Difference between the actual output value of the DAC and the theoretical value when the maximum value is added to the input end. The conversion precision of a DAC converter varies depending on the structure of the chip integrated on the DAC and the interface circuit configuration. The ideal conversion precision value should be as small as possible. To achieve optimal DAC conversion precision, the DAC must have high resolution. In addition, errors in the devices or power supply of the interface circuits will affect the conversion precision. When the error exceeds a certain degree, a DAC conversion error will be caused.
- Conversion speed
The conversion speed is determined by the setup time. The setup time is the period from the time the input suddenly changes from all 0s to all 1s to the time the output voltage remains within the FSR ± ½LSB (or FSR ± x%FSR). It is the maximum response time of the DAC, and hence used to measure the conversion speed.
The full scale range (FSR) is the maximum range of the output signal amplitude of a DAC. Different DACs have different FSRs, which can be limited by positive and negative currents or voltages.
The least significant byte (LSB) refers to bit 0 (the least significant bit) in a binary number.
### Working Principles<a name="4"></a>
In the Hardware Driver Foundation (HDF), the DAC module uses the unified service mode for API adaptation. In this mode, a device service is used as the DAC manager to handle access requests from the devices of the same type in a unified manner. The unified service mode applies to the scenario where there are many device objects of the same type. If the independent service mode is used, more device nodes need to be configured and memory resources will be consumed by services. The figure below shows the unified service mode.
The DAC module is divided into the following layers:
- The interface layer provides APIs for opening or closing a device and writing data.
- The core layer provides the capabilities of binding, initializing, and releasing devices.
- The adaptation layer implements other functions.
![](../public_sys-resources/icon-note.gif)NOTE<br/>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer.
**Figure 1** Unified service mode<a name="fig14423182615525"></a>
![](figures/unified-service-mode.png "DAC unified service mode")
### Constraints<a name="5"></a>
Currently, the DAC module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines<a name="6"></a>
### When to Use<a name="7"></a>
The DAC module is used for digital-to-analog conversion, audio output, and motor control. The DAC driver is used when the digital signals input by the DAC module are converted into analog signals to output.
### Available APIs<a name="8"></a>
The **DacMethod** is used to call the DAC driver functions.
**DacMethod** definition:
```
struct DacMethod {
// Hook used to write data.
int32_t (*write)(struct DacDevice *device, uint32_t channel, uint32_t val);
// Hook used to start a DAC device.
int32_t (*start)(struct DacDevice *device);
// Hook used to stop a DAC device
int32_t (*stop)(struct DacDevice *device);
};
```
**Table 1** Description of the DacMethod structure
<a name="table27410339187"></a>
| Function| Input Parameter | Output Parameter| Return Value | Description |
| -------- | ------------------------------------------------------------ | ---- | ------------------ | -------------- |
| write | **device**: pointer to the DAC controller at the core layer.<br>**channel**: channel ID, which is of the uint32_t type.<br>val: data to write, which is of the uint32_t type.| - | HDF_STATUS| Writes the target digit-to-analog (DA) value.|
| start | **device**: pointer to the DAC controller at the core layer. | - | HDF_STATUS| Starts a DAC device. |
| stop | **device**: pointer to the DAC controller at the core layer. | - | HDF_STATUS| Stops a device. |
### How to Develop<a name="9"></a>
The DAC module adaptation procedure is as follows:
- Instantiate the driver entry.
- Configure attribute files.
- Instantiate the APIs of the core layer.
- Debug the driver.
1. Instantiate the driver entry.
Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
```
static struct HdfDriverEntry g_dacDriverEntry = {
.moduleVersion = 1,
.Init = VirtualDacInit,
.Release = VirtualDacRelease,
.moduleName = "virtual_dac_driver",// (Mandatory) The value must be the same as that in the .hcs file.
};
HDF_INIT(g_dacDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
2. Configure attribute files.
- Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
The device attribute values are closely related to the driver implementation and the default values or restriction ranges of the **DacDevice** members at the core layer, for example, the number of device channels and the maximum transmission speed.
In the unified service mode, the first device node in the **device_info.hcs** file must be the DAC manager. The parameters must be set as follows:
| Member | Value |
| --------------- | ------------------------------------------------------------ |
| policy | **0**, which indicates that no service is published.|
| priority | Driver startup priority. The value range is 0 to 200. A larger value indicates a lower priority. If the priorities are the same, the device loading sequence is not ensured.|
| permission | Driver permission.|
| moduleName | The value is **HDF_PLATFORM_DAC_MANAGER**.|
| serviceName | The value is **HDF_PLATFORM_DAC_MANAGER**.|
| deviceMatchAttr | Reserved.|
Configure DAC controller information from the second node. This node specifies a type of DAC controllers rather than a specific DAC controller. In this example, there is only one DAC device. If there are multiple DAC devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **dac_config** file.
**device_info.hcs** configuration reference
```
root {
device_dac :: device {
// device0 is the DAC manager.
device0 :: deviceNode {
policy = 0;
priority = 52;
permission = 0644;
serviceName = "HDF_PLATFORM_DAC_MANAGER";
moduleName = "HDF_PLATFORM_DAC_MANAGER";
}
}
// dac_virtual is the DAC controller.
dac_virtual :: deviceNode {
policy = 0;
priority = 56;
permission = 0644;
moduleName = "virtual_dac_driver"; // (Mandatory) Driver name, which must be the same as moduleName in the driver entry.
serviceName = "VIRTUAL_DAC_DRIVER"; // (Mandatory) Unique name of the service published by the driver.
deviceMatchAttr = "virtual_dac"; // (Mandatory) Controller private data, which must be same as that of the corresponding controller in dac_config.hcs.
}
}
```
- Configure the **dac_test_config.hcs** file.
Add a file, for example, **vendor/vendor_hisilicon/hispark_taurus/hdf_config/hdf_test/dac_test_config.hcs** and configure driver parameters.
```
root {
platform {
dac_config {
match_attr = "virtual_dac"; // (Mandatory) The value must be the same as that of deviceMatchAttr in device_info.hcs.
template dac_device {
deviceNum = 0; // Device number.
validChannel = 0x1; // Valid channel 1.
rate = 20000; // Transmission speed.
}
device_0 :: dac_device {
deviceNum = 0; // Device number.
validChannel = 0x2; // Valid channel 2.
}
}
}
}
```
3. Instantiate the APIs of the core layer.
- Initialize the **DacDevice** object.
Initialize the **DacDevice** member in the **VirtualDacParseAndInit** function.
```
// Custom structure of the virtual driver
struct VirtualDacDevice {
// DAC device structure
struct DacDevice device;
// DAC device number
uint32_t deviceNum;
// Valid channel
uint32_t validChannel;
// DAC rate
uint32_t rate;
};
// Parse and initialize the **DacDevice** object of the core layer.
static int32_t VirtualDacParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
// Define the return values.
int32_t ret;
// Virtual pointer to the DAC device
struct VirtualDacDevice *virtual = NULL;
(void)device;
// Allocate space for the virtual pointer.
virtual = (struct VirtualDacDevice *)OsalMemCalloc(sizeof(*virtual));
if (virtual == NULL) {
// If the value is null, return an error code.
HDF_LOGE("%s: Malloc virtual fail!", __func__);
return HDF_ERR_MALLOC_FAIL;
}
// Read the configuration of the attribute file.
ret = VirtualDacReadDrs(virtual, node);
if (ret != HDF_SUCCESS) {
// Failed to read the file.
HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret);
// Release the virtual space.
OsalMemFree(virtual);
// Set the pointer to 0.
virtual = NULL;
return ret;
}
// Initialize the virtual pointer.
VirtualDacDeviceInit(virtual);
// Initialize the priv object in DacDevice.
virtual->device.priv = (void *)node;
// Initialize the devNum object in DacDevice.
virtual->device.devNum = virtual->deviceNum;
// Initialize the ops object in DacDevice.
virtual->device.ops = &g_method;
// Add a DAC device.
ret = DacDeviceAdd(&virtual->device);
if (ret != HDF_SUCCESS) {
// Failed to add the device.
HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret);
// Release the virtual space.
OsalMemFree(virtual);
// Set the virtual pointer to null.
virtual = NULL;
return ret;
}
return HDF_SUCCESS;
}
```
- Custom structure reference
The custom structure holds parameters and data for the driver. Define the custom structure based on the function parameters of the device. The HDF reads the values in the **dac_config.hcs** file using the **DacTestReadConfig()** function and initializes the structure members using **DeviceResourceIface()**. Some important values, such as the device number and bus number, are also passed to the **DacDevice** object at the core layer.
```
struct VirtualDacDevice {
struct DacDevice device;// (Mandatory) Control object at the core layer. For details, see the description below.
uint32_t deviceNum; // (Mandatory) Device number.
uint32_t validChannel; // (Mandatory) Valid channel.
uint32_t rate; // (Mandatory) Sampling rate.
};
// DacDevice is the core layer controller structure. Its members are assigned with values in the Init() function.
struct DacDevice {
const struct DacMethod *ops;
OsalSpinlock spin; // Spinlock.
uint32_t devNum; // Device number.
uint32_t chanNum; // Device channel number.
const struct DacLockMethod *lockOps;
void *priv;
};
```
- Instantiate the **DacDevice** in **DacMethod**.
The **VirtualDacWrite**, **VirtualDacStop**, and **VirtualDacStart** functions are instantiated in **dac_virtual.c**.
```
static const struct DacMethod g_method = {
.write = VirtualDacWrite, // Write data to a DAC device.
.stop = VirtualDacStop, // Stop a DAC device.
.start = VirtualDacStart, // Start a DAC device.
};
```
![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
For details about **DacMethod**, see [Available APIs](#section752964871810).
- **Init** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return value:
HDF_STATUS (The table below lists some status. For details about other status, see HDF_STATUS in the /drivers/framework/include/utils/hdf_base.h file.)
| State | Description |
| ---------------------- | -------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| HDF_ERR_INVALID_PARAM | Invalid parameter. |
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
| HDF_ERR_IO | I/O error. |
| HDF_SUCCESS | Transmission successful. |
| HDF_FAILURE | Transmission failed. |
Function description:
Initializes the custom structure object and **DacDevice**, and calls the **AdcDeviceAdd** function at the core layer.
```
static int32_t VirtualDacParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{
// Define return value parameters.
int32_t ret;
// Pointer to the DAC device.
struct VirtualDacDevice *virtual = NULL;
(void)device;
// Allocate memory of the specified size.
virtual = (struct VirtualDacDevice *)OsalMemCalloc(sizeof(*virtual));
if (virtual == NULL) {
// Failed to allocate memory.
HDF_LOGE("%s: Malloc virtual fail!", __func__);
return HDF_ERR_MALLOC_FAIL;
}
// Read the node parameters in the .hcs file.
ret = VirtualDacReadDrs(virtual, node);
if (ret != HDF_SUCCESS) {
// Failed to read the node data.
HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret);
goto __ERR__;
}
// Initialize the DAC device pointer.
VirtualDacDeviceInit(virtual);
// Pass private node data.
virtual->device.priv = (void *)node;
// Pass the device number.
virtual->device.devNum = virtual->deviceNum;
// Pass the method.
virtual->device.ops = &g_method;
// Add a DAC device.
ret = DacDeviceAdd(&virtual->device);
if (ret != HDF_SUCCESS) {
// Failed to add the DAC device.
HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret);
goto __ERR__;
}
// The DAC device is added.
return HDF_SUCCESS;
__ERR__:
// If the pointer is null
if (virtual != NULL) {
// Release the memory.
OsalMemFree(virtual);
// Set the pointer to null.
virtual = NULL;
}
return ret;
}
static int32_t VirtualDacInit(struct HdfDeviceObject *device)
{
// Define return value parameters.
int32_t ret;
// Child node of the device structure
const struct DeviceResourceNode *childNode = NULL;
// Check the input parameter pointer.
if (device == NULL || device->property == NULL) {
// The input parameter pointer is null.
HDF_LOGE("%s: device or property is NULL", __func__);
return HDF_ERR_INVALID_OBJECT;
}
// The input parameter pointer is not null.
ret = HDF_SUCCESS;
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
// Parse the child node.
ret = VirtualDacParseAndInit(device, childNode);
if (ret != HDF_SUCCESS) {
// Failed to parse the child node.
break;
}
}
// The child node is parsed.
return ret;
}
```
- **Release** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration file information.
Return value
This function returns no value.
Function description:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. 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 VirtualDacRemoveByNode(const struct DeviceResourceNode *node)
{
// Define return value parameters.
int32_t ret;
// Define the DAC device number.
int16_t devNum;
// Pointer of the DacDevice structure.
struct DacDevice *device = NULL;
// Pointer of the VirtualDacDevice structure.
struct VirtualDacDevice *virtual = NULL;
// Pointer of the DeviceResourceIface structure.
struct DeviceResourceIface *drsOps = NULL;
// Obtain device resources through the instance entry.
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
// Check the input parameter pointer.
if (drsOps == NULL || drsOps->GetUint32 == NULL) {
// The pointer is null.
HDF_LOGE("%s: invalid drs ops fail!", __func__);
return;
}
// Obtain data of the devNum node.
ret = drsOps->GetUint16(node, "devNum", (uint16_t *)&devNum, 0);
if (ret != HDF_SUCCESS) {
// Failed to obtain node data.
HDF_LOGE("%s: read devNum fail!", __func__);
return;
}
// Obtain the DAC device number.
device = DacDeviceGet(devNum);
// Check whether the DAC device number and data are null.
if (device != NULL && device->priv == node) {
// Release the DAC device number if the device data is null.
DacDevicePut(device);
// Remove the DAC device number.
DacDeviceRemove(device);
virtual = (struct VirtualDacDevice *)device;
// Release the virtual pointer.
OsalMemFree(virtual);
}
return;
}
static void VirtualDacRelease(struct HdfDeviceObject *device)
{
// Define the child node structure pointer of the DeviceResourceNode.
const struct DeviceResourceNode *childNode = NULL;
// Check whether the input parameter pointer is null.
if (device == NULL || device->property == NULL) {
// The input parameter pointer is null.
HDF_LOGE("%s: device or property is NULL", __func__);
return;
}
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
// Remove the DAC through the node.
VirtualDacRemoveByNode(childNode);
}
}
```
4. Debug the driver.
(Optional) Verify the basic functions of the new driver, for example, whether the test cases are successful after the driver is loaded.
# HDMI<a name="1"></a> # HDMI
## Overview<a name="section1"></a>
High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba. ## Overview
HDMI works in master/slave mode and usually has a source and a sink. ### HDMI
The HDMI APIs provide a set of common functions for HDMI transmission, including: - High-definition multimedia interface (HDMI) is an interface for transmitting audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display.
- HDMI works in master/slave mode and usually has a source and a sink.
- The HDMI APIs provide a set of common functions for HDMI transmission, including:
- Opening and closing an HDMI controller - Opening and closing an HDMI controller
- Starting and stopping HDMI transmission - Starting and stopping HDMI transmission
- Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute - Setting audio, video, and High Dynamic Range (HDR) attributes, color depth, and AV mute
- Reading the raw Extended Display Identification Data (EDID) from a sink - Reading the raw Extended Display Identification Data (EDID) from a sink
- Registering and unregistering a callback for HDMI hot plug detect (HPD) - Registering and unregistering a callback for HDMI hot plug detect (HPD).
[Figure 1](#fig1) shows the HDMI physical connection. ### Basic Concepts
**Figure 1** HDMI physical connection<a name="fig1"></a> HDMI is an audio and video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba. The transmission process complies with the Transition-minimized Differential Signaling (TMDS).
![](figures/HDMI_physical_connection.png "HDMI_physical_connection") - TMDS is used to transmit audio, video, and various auxiliary data.
- Display data channel (DDC) allows the TX and RX ends to obtain the sending and receiving capabilities. However, the HDMI only needs to unidirectionally obtain the capabilities of the RX end (display).
- Consumer Electronics Control (CEC) enables interaction between the HDMI TX and RX devices.
- Fixed rate link (FRL) allows the maximum TMDS bandwidth to be increased from 18 Gbit/s to 48 Gbit/s.
- High-bandwidth Digital Content Protection (HDCP) prevents copying of digital audio and video content being transmitted across devices.
- Extended Display Identification Data (EDID), usually stored in the display firmware, provides the vendor information, EDID version, maximum image size, color settings, vendor pre-settings, frequency range limit, display name, and serial number.
## Available APIs<a name="section2"></a> ### Working Principles
The HDMI source end provides +5 V and GND for DDC and CEC communication. Through the DDC, the source end obtains the sink end parameters, such as the RX capabilities. The CEC is optional. It is used to synchronize the control signals between the source and sink ends to improve user experience. There are four TMDS channels between the HDMI source and sink ends. The TMDS clock channel provides clock signals for TMDS, and the other three channels transmit audio, video, and auxiliary data. HPD is the hot plug detect port. When the sink end is connected, the source end responds by using an interrupt program.
The figure below shows the HDMI physical connection.
**Figure 1** HDMI physical connection
![](figures/HDMI_physical_connection.png "HDMI_physical_connection")
### Constraints
Currently, the HDMI module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
HDMI features high transmission rate, wide transmission bandwidth, high compatibility, and can transmit uncompressed audio and video signals. Compared with the traditional full analog interface, HDMI simplifies connection between devices and provides HDMI-specific intelligent features, which are ideal for high-quality audio and video transmission of small-sized devices.
### Available APIs
**Table 1** HDMI driver APIs **Table 1** HDMI driver APIs
<a name="table1"></a>
| API | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="18.63%"><p>Category</p> | ----------------------------- | -------------------------- |
</th> | HdmiOpen | Opens an HDMI controller. |
<th class="cellrowborder" valign="top" width="28.03%"><p>API</p> | HdmiClose | Closes an HDMI controller. |
</th> | HdmiStart | Starts HDMI transmission. |
<th class="cellrowborder" valign="top" width="53.339999999999996%"><p>Description</p> | HdmiStop | Stops HDMI transmission. |
</th> | HdmiAvmuteSet | Sets the AV mute feature. |
</tr> | HdmiDeepColorSet | Sets the color depth. |
</thead> | HdmiDeepColorGet | Obtains the color depth. |
<tbody><tr><td class="cellrowborder" bgcolor="#ffffff" rowspan="2" valign="top" width="18.63%"><p>Managing HDMI controllers</p> | HdmiSetVideoAttribute | Sets video attributes. |
</td> | HdmiSetAudioAttribute | Sets audio attributes. |
<td class="cellrowborder" valign="top" width="28.03%"><p>HdmiOpen</p> | HdmiSetHdrAttribute | Sets HDR attributes. |
</td> | HdmiReadSinkEdid | Reads the raw EDID from a sink. |
<td class="cellrowborder" valign="top" width="53.339999999999996%">Opens an HDMI controller.</p> | HdmiRegisterHpdCallbackFunc | Registers a callback for HDMI HPD.|
</td> | HdmiUnregisterHpdCallbackFunc | Unregisters a callback for HDMI HPD.|
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiClose</p> ### How to Develop
</td>
<td class="cellrowborder" valign="top"><p>Closes an HDMI controller.</p> The figure below illustrates the process of using an HDMI device.
</td>
</tr> **Figure 2** Process of using an HDMI device
<tr><td class="cellrowborder" bgcolor="#ffffff" rowspan="2" valign="top" width="18.63%"><p>Starting or stopping HDMI transmission</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%"><p>HdmiStart</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%">Starts HDMI transmission.</p>
</td>
</tr>
<tr id="row5632152611414"><td class="cellrowborder" valign="top"><p>HdmiStop</p>
</td>
<td class="cellrowborder" valign="top"><p>Stops HDMI transmission.</p>
</td>
</tr>
<tr><td class="cellrowborder" bgcolor="#ffffff" rowspan="6" valign="top" width="18.63%"><p>Setting an HDMI controller</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%"><p>HdmiAvmuteSet</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%">Sets the AV mute feature.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiDeepColorSet</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.2.4.1.2 "><p>Sets the color depth.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiDeepColorGet</p>
</td>
<td class="cellrowborder" valign="top"><p>Obtains the color depth.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiSetVideoAttribute</p>
</td>
<td class="cellrowborder" valign="top"><p>Sets video attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiSetAudioAttribute</p>
</td>
<td class="cellrowborder" valign="top"><p>Sets audio attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiSetHdrAttribute</p>
</td>
<td class="cellrowborder" valign="top"><p>Sets HDR attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" bgcolor="#ffffff" valign="top" width="18.63%"><p>Reading EDID</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%"><p>HdmiReadSinkEdid</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%">Reads the raw EDID from a sink.</p>
</td>
</tr>
<tr><td class="cellrowborder" bgcolor="#ffffff" rowspan="2" valign="top" width="18.63%"><p>Registering or unregistering a callback for HDMI HPD</p>
</td>
<td class="cellrowborder" valign="top" width="28.03%"><p>HdmiRegisterHpdCallbackFunc</p>
</td>
<td class="cellrowborder" valign="top" width="53.339999999999996%">Registers a callback for HDMI HPD.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top"><p>HdmiUnregisterHpdCallbackFunc</p>
</td>
<td class="cellrowborder" valign="top"><p>Unregisters the callback for HDMI HPD.</p>
</td>
</tr>
</tbody>
</table>
## Usage Guidelines<a name="section3"></a>
### How to Use<a name="section4"></a>
[Figure 2](#fig2) shows how HDMI works.
**Figure 2** How HDMI works<a name="fig2"></a>
![](figures/HDMI_usage_flowchart.png "HDMI_usage_flowchart") ![](figures/HDMI_usage_flowchart.png "HDMI_usage_flowchart")
### Opening an HDMI Controller<a name="section5"></a> #### Opening an HDMI Controller
Before HDMI communication, call **HdmiOpen** to open an HDMI controller. Before HDMI communication, call **HdmiOpen** to open an HDMI controller.
...@@ -132,38 +85,14 @@ DevHandle HdmiOpen(int16_t number); ...@@ -132,38 +85,14 @@ DevHandle HdmiOpen(int16_t number);
**Table 2** Description of HdmiOpen **Table 2** Description of HdmiOpen
<a name="table2"></a> | Parameter | Description |
| ---------- | -------------------- |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="20.66%"><p> Parameter</strong></p> | number | HDMI controller ID. |
</th> | **Return Value**| **Description** |
<th class="cellrowborder" valign="top" width="79.34%"><p><strong>Description</strong></p> | NULL | Failed to open the HDMI controller. |
</th> | Controller handle| Handle of the opened HDMI controller.|
</tr>
</thead> Example: Open controller 0 of the two HDMI controllers (numbered 0 and 1) in the system.
<tbody><tr><td class="cellrowborder" valign="top" width="20.66%"><p>number</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%"><p>HDMI controller ID.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="20.66%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="79.34%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="20.66%"><p>NULL</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%"><p>Failed to open the HDMI controller.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="20.66%"><p>Controller handle</p>
</td>
<td class="cellrowborder" valign="top" width="79.34%"><p>Handle of the HDMI controller opened.</p>
</td>
</tr>
</tbody>
</table>
For example, the system has two HDMI controllers, numbered 0 and 1. Open controller 0.
```c ```c
DevHandle hdmiHandle = NULL; /* HDMI controller handle / DevHandle hdmiHandle = NULL; /* HDMI controller handle /
...@@ -176,7 +105,7 @@ if (hdmiHandle == NULL) { ...@@ -176,7 +105,7 @@ if (hdmiHandle == NULL) {
} }
``` ```
### Registering a Callback for HPD<a name="section6"></a> #### Registering a Callback for HPD
```c ```c
int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback); int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo *callback);
...@@ -184,41 +113,13 @@ int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo ...@@ -184,41 +113,13 @@ int32_t HdmiRegisterHpdCallbackFunc(DevHandle handle, struct HdmiHpdCallbackInfo
**Table 3** Description of HdmiRegisterHpdCallbackFunc **Table 3** Description of HdmiRegisterHpdCallbackFunc
<a name="table3"></a> | Parameter | Description |
| ---------- | ------------------ |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | handle | HDMI controller handle. |
</th> | callback | Pointer to the callback to be invoked to return the HPD result.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | **Return Value**| **Description** |
</th> | 0 | The operation is successful. |
</tr> | Negative value | The operation failed. |
</thead>
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>callback</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the callback to be invoked to return the HPD result.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The callback is registered successfully.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Failed to register the callback.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of registering a callback for HPD: The following is an example of registering a callback for HPD:
...@@ -227,30 +128,31 @@ The following is an example of registering a callback for HPD: ...@@ -227,30 +128,31 @@ The following is an example of registering a callback for HPD:
static void HdmiHpdHandle(void *data, bool hpd) static void HdmiHpdHandle(void *data, bool hpd)
{ {
if (data == NULL) { if (data == NULL) {
HDF_LOGE("priv data is NULL"); HDF_LOGE("priv data is NULL");
return; return;
} }
if (hpd == true) { if (hpd == true) {
HDF_LOGD("HdmiHpdHandle: hot plug"); HDF_LOGD("HdmiHpdHandle: hot plug");
/* Add related processing if required. */ /* Add related processing if required. */
} else { } else {
HDF_LOGD("HdmiHpdHandle: hot unplog"); HDF_LOGD("HdmiHpdHandle: hot unplug");
/* Add related processing if required. */ /* Add related processing if required. */
} }
} }
/* Example of registering a callback for HPD */ /* Example of registering a callback for HPD */
struct HdmiHpdCallbackInfo info = {0}; ···
info.data = handle; struct HdmiHpdCallbackInfo info = {0};
info.callbackFunc = HdmiHpdHandle; info.data = handle;
ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info); info.callbackFunc = HdmiHpdHandle;
if (ret != 0) { ret = HdmiRegisterHpdCallbackFunc(hdmiHandle, info);
HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register failed."); if (ret != 0) {
} HDF_LOGE("HdmiRegisterHpdCallbackFunc: Register failed.");
}
···
``` ```
### Reading the RAW EDID<a name="section7"></a> #### Reading the Raw EDID
```c ```c
int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len); int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
...@@ -258,46 +160,14 @@ int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len); ...@@ -258,46 +160,14 @@ int32_t HdmiReadSinkEdid(DevHandle handle, uint8_t *buffer, uint32_t len);
**Table 4** Description of HdmiReadSinkEdid **Table 4** Description of HdmiReadSinkEdid
<a name="table4"></a> | Parameter | Description |
| ---------- | ---------------------- |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | handle | HDMI controller handle. |
</th> | buffer | Pointer to the data buffer. |
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | len | Data length. |
</th> | **Return Value**| **Description** |
</tr> | Positive integer | Raw EDID read.|
</thead> | Negative number or 0 | Failed to read the EDID. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>buffer</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the data buffer.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>len</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Data length.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Positive integer</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Raw EDID read.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number or **0**</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Failed to read the EDID.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of reading the raw EDID from a sink: The following is an example of reading the raw EDID from a sink:
...@@ -311,8 +181,6 @@ if (len <= 0) { ...@@ -311,8 +181,6 @@ if (len <= 0) {
} }
``` ```
### Setting Video, Audio, and HDR Attributes<a name="section8"></a>
#### Setting Audio Attributes #### Setting Audio Attributes
```c ```c
...@@ -321,41 +189,14 @@ int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr); ...@@ -321,41 +189,14 @@ int32_t HdmiSetAudioAttribute(DevHandle handle, struct HdmiAudioAttr *attr);
**Table 5** Description of HdmiSetAudioAttribute **Table 5** Description of HdmiSetAudioAttribute
<a name="table5"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ------ | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | attr | Pointer to the audio attributes. |
</th> | **Return Value**| **Description** |
</tr> | 0 | The operation is successful. |
</thead> | Negative value | The operation failed. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>attr</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the audio attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of setting audio attributes: The following is an example of setting audio attributes:
...@@ -382,41 +223,14 @@ int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr); ...@@ -382,41 +223,14 @@ int32_t HdmiSetVideoAttribute(DevHandle handle, struct HdmiVideoAttr *attr);
**Table 6** Description of HdmiSetVideoAttribute **Table 6** Description of HdmiSetVideoAttribute
<a name="table6"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | attr | Pointer to the video attributes. |
</th> | **Return Value**| **Description**|
</tr> | 0 | The operation is successful. |
</thead> | Negative value | The operation failed. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>attr</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the video attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of setting video attributes: The following is an example of setting video attributes:
...@@ -442,41 +256,14 @@ int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr); ...@@ -442,41 +256,14 @@ int32_t HdmiSetHdrAttribute(DevHandle handle, struct HdmiHdrAttr *attr);
**Table 7** Description of HdmiSetHdrAttribute **Table 7** Description of HdmiSetHdrAttribute
<a name="table7"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | attr | Pinter to the HDR attributes. |
</th> | **Return Value**| **Description**|
</tr> | 0 | The operation is successful. |
</thead> | Negative value | The operation failed. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>attr</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the HDR attributes.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of setting HDR attributes: The following is an example of setting HDR attributes:
...@@ -495,8 +282,6 @@ if (ret != 0) { ...@@ -495,8 +282,6 @@ if (ret != 0) {
} }
``` ```
### Setting Other Attributes<a name="section9"></a>
#### Setting HDMI AV Mute #### Setting HDMI AV Mute
```c ```c
...@@ -505,41 +290,14 @@ int32_t HdmiAvmuteSet(DevHandle handle, bool enable); ...@@ -505,41 +290,14 @@ int32_t HdmiAvmuteSet(DevHandle handle, bool enable);
**Table 8** Description of HdmiAvmuteSet **Table 8** Description of HdmiAvmuteSet
<a name="table8"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | ----------------- |
</th> | handle | HDMI controller handle. |
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | enable | Whether to enable the AV mute feature.|
</th> | **Return Value**| **Description** |
</tr> | 0 | The operation is successful. |
</thead> | Negative value | The operation failed. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>enable</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Whether the AV mute feature is enabled.
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of setting AV mute: The following is an example of setting AV mute:
...@@ -560,41 +318,14 @@ int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color); ...@@ -560,41 +318,14 @@ int32_t HdmiDeepColorSet(DevHandle handle, enum HdmiDeepColor color);
**Table 9** Description of HdmiDeepColorSet **Table 9** Description of HdmiDeepColorSet
<a name="table9"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | color | Color depth to set. |
</th> | **Return Value**| **Description**|
</tr> | 0 | The operation is successful. |
</thead> | Negative value | The operation failed. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>color</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Color depth to set.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of setting the color depth: The following is an example of setting the color depth:
...@@ -615,41 +346,14 @@ int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color); ...@@ -615,41 +346,14 @@ int32_t HdmiDeepColorGet(DevHandle handle, enum HdmiDeepColor *color);
**Table 10** Description of HdmiDeepColorGet **Table 10** Description of HdmiDeepColorGet
<a name="table10"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | color | Pointer to the color depth. |
</th> | **Return Value**| **Description**|
</tr> | 0 | The operation is successful. |
</thead> | Negative value | The operation failed. |
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>color</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>Pointer to the color depth.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of obtaining the color depth: The following is an example of obtaining the color depth:
...@@ -663,7 +367,7 @@ if (ret != 0) { ...@@ -663,7 +367,7 @@ if (ret != 0) {
} }
``` ```
### Starting HDMI Transmission<a name="section10"></a> #### Starting HDMI Transmission
```c ```c
int32_t HdmiStart(DevHandle handle); int32_t HdmiStart(DevHandle handle);
...@@ -671,36 +375,13 @@ int32_t HdmiStart(DevHandle handle); ...@@ -671,36 +375,13 @@ int32_t HdmiStart(DevHandle handle);
**Table 11** Description of HdmiStart **Table 11** Description of HdmiStart
<a name="table11"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | **Return Value**| **Description**|
</th> | 0 | The operation is successful. |
</tr> | Negative value | The operation failed. |
</thead>
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of starting HDMI transmission: The following is an example of starting HDMI transmission:
...@@ -713,7 +394,7 @@ if (ret != 0) { ...@@ -713,7 +394,7 @@ if (ret != 0) {
} }
``` ```
### Stopping HDMI Transmission<a name="section11"></a> #### Stopping HDMI Transmission<a name="section11"></a>
```c ```c
int32_t HdmiStop(DevHandle handle); int32_t HdmiStop(DevHandle handle);
...@@ -721,36 +402,13 @@ int32_t HdmiStop(DevHandle handle); ...@@ -721,36 +402,13 @@ int32_t HdmiStop(DevHandle handle);
**Table 12** Description of HdmiStop **Table 12** Description of HdmiStop
<a name="table12"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | **Return Value**| **Description**|
</th> | 0 | The operation is successful. |
</tr> | Negative value | The operation failed. |
</thead>
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of stopping HDMI transmission: The following is an example of stopping HDMI transmission:
...@@ -763,7 +421,7 @@ if (ret != 0) { ...@@ -763,7 +421,7 @@ if (ret != 0) {
} }
``` ```
### Unregistering the Callback for HPD<a name="section12"></a> #### Unregistering the Callback for HPD
```c ```c
int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle); int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);
...@@ -771,36 +429,13 @@ int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle); ...@@ -771,36 +429,13 @@ int32_t HdmiUnregisterHpdCallbackFunc(DevHandle handle);
**Table 13** Description of HdmiUnregisterHpdCallbackFunc **Table 13** Description of HdmiUnregisterHpdCallbackFunc
<a name="table13"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p> | **Return Value**| **Description**|
</th> | 0 | The operation is successful. |
</tr> | Negative value | The operation failed. |
</thead>
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p><strong>Return Value</strong></p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>0</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation is successful.</p>
</td>
</tr>
<tr><td class="cellrowborder" valign="top" width="50%"><p>Negative number</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>The operation failed.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of unregistering the callback for HPD: The following is an example of unregistering the callback for HPD:
...@@ -813,7 +448,7 @@ if (ret != 0) { ...@@ -813,7 +448,7 @@ if (ret != 0) {
} }
``` ```
### Closing an HDMI Controller<a name="section13"></a> #### Closing an HDMI Controller
```c ```c
void HdmiClose(DevHandle handle); void HdmiClose(DevHandle handle);
...@@ -821,21 +456,10 @@ void HdmiClose(DevHandle handle); ...@@ -821,21 +456,10 @@ void HdmiClose(DevHandle handle);
**Table 14** Description of HdmiClose **Table 14** Description of HdmiClose
<a name="table14"></a>
| Parameter | Description |
<table><thead align="left"><tr><th class="cellrowborder" valign="top" width="50%"><p><strong> Parameter</strong></p> | ---------- | -------------- |
</th> | handle | HDMI controller handle.|
<th class="cellrowborder" valign="top" width="50%"><p><strong>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr><td class="cellrowborder" valign="top" width="50%"><p>handle</p>
</td>
<td class="cellrowborder" valign="top" width="50%"><p>HDMI controller handle.</p>
</td>
</tr>
</tbody>
</table>
The following is an example of closing an HDMI controller: The following is an example of closing an HDMI controller:
...@@ -843,7 +467,7 @@ The following is an example of closing an HDMI controller: ...@@ -843,7 +467,7 @@ The following is an example of closing an HDMI controller:
HdmiClose(hdmiHandle); HdmiClose(hdmiHandle);
``` ```
## Example<a name="section14"></a> ### Development Example
This following example shows how to use HDMI APIs to manage an HDMI device on a Hi3516D V300 development board. This following example shows how to use HDMI APIs to manage an HDMI device on a Hi3516D V300 development board.
...@@ -873,7 +497,7 @@ static void HdmiHpdHandle(void *data, bool hpd) ...@@ -873,7 +497,7 @@ static void HdmiHpdHandle(void *data, bool hpd)
HDF_LOGD("HdmiHpdHandle: hot plug"); HDF_LOGD("HdmiHpdHandle: hot plug");
/* Add related processing if required. */ /* Add related processing if required. */
} else { } else {
HDF_LOGD("HdmiHpdHandle: hot unplog"); HDF_LOGD("HdmiHpdHandle: hot unplug");
/* Add related processing if required. */ /* Add related processing if required. */
} }
} }
......
# HDMI # HDMI
## Overview<a name="1"></a> ## Overview
High-Definition Multimedia Interface (HDMI) is an audio/video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba. It is used to transmit audio or video data from an audio or video source device, such as a DVD player or STB, to a sink device, such as a TV or monitor. The transmission process complies with the Transition Minimized Differential Signaling (TMDS) protocol. ### HDMI
High-definition multimedia interface (HDMI) is an interface for transmitting audio and video data from a source device, such as a DVD player or set-top box (STB), to a sink device, such as a TV or display.
### Basic Concepts
HDMI is an audio and video transmission protocol released by Hitachi, Panasonic, Philips, Silicon Image, Sony, Thomson, and Toshiba. The transmission process complies with the Transition Minimized Differential Signaling (TMDS) protocol.
- TMDS is used to transmit audio, video, and various auxiliary data.
- Display data channel (DDC) allows the TX and RX ends to obtain the sending and receiving capabilities. However, the HDMI only needs to unidirectionally obtain the capabilities of the RX end (display).
- Consumer Electronics Control (CEC) enables interaction between the HDMI TX and RX devices.
- Fixed rate link (FRL) allows the maximum TMDS bandwidth to be increased from 18 Gbit/s to 48 Gbit/s.
- High-bandwidth Digital Content Protection (HDCP) prevents copying of digital audio and video content being transmitted across devices.
### Working Principles
In the HDF, the HDMI module uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to process external access requests. After receiving an access request, 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 node for each device, which increases the memory usage. In the HDF, the HDMI module uses the independent service mode for API adaptation. In this mode, each device independently publishes a device service to process external access requests. After receiving an access request, 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 node for each device, which increases the memory usage.
**Figure 1** Independent service mode<a name="fig1"></a> **Figure 1** Independent service mode
![image1](figures/independent-service-mode.png) ![image1](figures/independent-service-mode.png)
## Available APIs<a name="2"></a> ### Constraints
**HdmiCntlrOps**: Currently, the HDMI module supports only the kernels (LiteOS) of mini and small systems.
```c
struct HdmiCntlrOps { ## Development Guidelines
void (*hardWareInit)(struct HdmiCntlr *cntlr);
void (*hardWareStatusGet)(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *status);
void (*controllerReset)(struct HdmiCntlr *cntlr);
bool (*hotPlugStateGet)(struct HdmiCntlr *cntlr);
bool (*hotPlugInterruptStateGet)(struct HdmiCntlr *cntlr);
void (*lowPowerSet)(struct HdmiCntlr *cntlr, bool enable);
void (*tmdsModeSet)(struct HdmiCntlr *cntlr, enum HdmiTmdsModeType mode);
int32_t (*tmdsConfigSet)(struct HdmiCntlr *cntlr, struct HdmiTmdsConfig mode);
void (*infoFrameEnable)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, bool enable);
int32_t (*infoFrameSend)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, uint8_t *data, uint32_t len);
int32_t (*infoFrameDataSet)(struct HdmiCntlr *cntlr, uint32_t type, uint8_t *data, uint32_t len);
int32_t (*cecMsgSend)(struct HdmiCntlr *cntlr, struct HdmiCecMsg *msg);
void (*audioPathEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*audioPathSet)(struct HdmiCntlr *cntlr, struct HdmiAudioConfigInfo *config);
void (*phyOutputEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*phyOutputSet)(struct HdmiCntlr *cntlr, struct HdmiPhyCfg *cfg);
void (*blackDataSet)(struct HdmiCntlr *cntlr, bool enable);
void (*videoMuteEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*videoPathSet)(struct HdmiCntlr *cntlr, struct HdmiVideoAttr *attr);
void (*audioMuteEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*avmuteSet)(struct HdmiCntlr *cntlr, bool enable);
int32_t (*ddcTransfer)(struct HdmiCntlr *cntlr, struct HdmiDdcCfg *ddcCfg);
bool (*scdcSourceScrambleGet)(struct HdmiCntlr *cntlr);
int32_t (*scdcSourceScrambleSet)(struct HdmiCntlr *cntlr, bool enable);
void (*frlSet)(struct HdmiCntlr *cntlr);
int32_t (*frlEnable)(struct HdmiCntlr *cntlr, bool enable);
int32_t (*audioNctsSet)(struct HdmiCntlr *cntlr, struct HdmiFrlAudioNctsConfig *cfg);
void (*frlTrainingConfigSet)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainConfig *cfg);
void (*frlTrainingStart)(struct HdmiCntlr *cntlr);
void (*frlGetTriningRslt)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainRslt *rslt);
void (*hdcpRegInit)(struct HdmiCntlr *cntlr);
int32_t (*hdcpGenerateAksvAndAn)(struct HdmiCntlr *cntlr);
int32_t (*hdcpOptReg)(struct HdmiCntlr *cntlr, enum HdmiHdcpRegOptType type, uint8_t *data, uint32_t len);
void (*hdrTimerSet)(struct HdmiCntlr *cntlr, struct HdmiHdrTimerConfig *config);
};
```
### Use Cases
HDMI features high transmission rate, wide transmission bandwidth, high compatibility, and can transmit uncompressed audio and video signals. Compared with the traditional full analog interface, HDMI simplifies connection between devices and provides HDMI-specific intelligent features, which are ideal for high-quality audio and video transmission of small-sized devices.
### Available APIs
**HdmiCntlrOps**:
```c
struct HdmiCntlrOps {
void (*hardWareInit)(struct HdmiCntlr *cntlr);
void (*hardWareStatusGet)(struct HdmiCntlr *cntlr, struct HdmiHardwareStatus *status);
void (*controllerReset)(struct HdmiCntlr *cntlr);
bool (*hotPlugStateGet)(struct HdmiCntlr *cntlr);
bool (*hotPlugInterruptStateGet)(struct HdmiCntlr *cntlr);
void (*lowPowerSet)(struct HdmiCntlr *cntlr, bool enable);
void (*tmdsModeSet)(struct HdmiCntlr *cntlr, enum HdmiTmdsModeType mode);
int32_t (*tmdsConfigSet)(struct HdmiCntlr *cntlr, struct HdmiTmdsConfig mode);
void (*infoFrameEnable)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, bool enable);
int32_t (*infoFrameSend)(struct HdmiCntlr *cntlr, enum HdmiPacketType infoFrameType, uint8_t *data, uint32_t len);
int32_t (*infoFrameDataSet)(struct HdmiCntlr *cntlr, uint32_t type, uint8_t *data, uint32_t len);
int32_t (*cecMsgSend)(struct HdmiCntlr *cntlr, struct HdmiCecMsg *msg);
void (*audioPathEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*audioPathSet)(struct HdmiCntlr *cntlr, struct HdmiAudioConfigInfo *config);
void (*phyOutputEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*phyOutputSet)(struct HdmiCntlr *cntlr, struct HdmiPhyCfg *cfg);
void (*blackDataSet)(struct HdmiCntlr *cntlr, bool enable);
void (*videoMuteEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*videoPathSet)(struct HdmiCntlr *cntlr, struct HdmiVideoAttr *attr);
void (*audioMuteEnable)(struct HdmiCntlr *cntlr, bool enable);
void (*avmuteSet)(struct HdmiCntlr *cntlr, bool enable);
int32_t (*ddcTransfer)(struct HdmiCntlr *cntlr, struct HdmiDdcCfg *ddcCfg);
bool (*scdcSourceScrambleGet)(struct HdmiCntlr *cntlr);
int32_t (*scdcSourceScrambleSet)(struct HdmiCntlr *cntlr, bool enable);
void (*frlSet)(struct HdmiCntlr *cntlr);
int32_t (*frlEnable)(struct HdmiCntlr *cntlr, bool enable);
int32_t (*audioNctsSet)(struct HdmiCntlr *cntlr, struct HdmiFrlAudioNctsConfig *cfg);
void (*frlTrainingConfigSet)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainConfig *cfg);
void (*frlTrainingStart)(struct HdmiCntlr *cntlr);
void (*frlGetTriningRslt)(struct HdmiCntlr *cntlr, struct HdmiFrlTrainRslt *rslt);
void (*hdcpRegInit)(struct HdmiCntlr *cntlr);
int32_t (*hdcpGenerateAksvAndAn)(struct HdmiCntlr *cntlr);
int32_t (*hdcpOptReg)(struct HdmiCntlr *cntlr, enum HdmiHdcpRegOptType type, uint8_t *data, uint32_t len);
void (*hdrTimerSet)(struct HdmiCntlr *cntlr, struct HdmiHdrTimerConfig *config);
};
```
**Table 1** Description of the HdmiCntlrOps structure
| Function | Input Parameter | Output Parameter | Return Value | Description |
| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- |
| hardWareInit | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Initializes the HDMI hardware.|
| hardWareStatusGet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>| **status**: pointer to the HDMI hardware status.| –| Obtains the HDMI hardware status. |
| controllerReset | **cntlr**: structure pointer to an HDMI controller at the core layer.| – | –| Resets an HDMI controller. |
| hotPlugStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer. | – | **bool**: HDMI hot-plug status.| Obtains the HDMI hot-plug status. |
| hotPlugInterruptStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer. | – | **bool**: HDMI hot-plug interrupt status.| Obtains the HDMI hot-plug interrupt status. |
| lowPowerSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable low power consumption.| – | –| Enables or disables low power consumption.|
| tmdsModeSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br>**mode**: TMDS mode.| – | –| Sets the TMDS mode. |
|tmdsConfigSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**mode**: TMDS parameters.|–|HDF_STATUS|Sets TMDS parameters.|
|infoFrameEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**infoFrameType**: packet type.<br>**enable**: whether to enable infoFrame.|–|–|Enables or disables infoFrame.|
|infoFrameSend|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**infoFrameType**: packet type.<br>**data**: pointer to infoFrame data.<br>**len**: data length.|–|HDF_STATUS|Sends an infoFrame.|
|cecMsgSend|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**msg**: pointer to the CEC message|–|HDF_STATUS|Sends a CEC message.|
|audioPathEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the audio path.|–|–|Enables or disables the audio path.|
|audioPathSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**config**: pointer to the audio path configuration.|–|–|Sets the audio path.|
|phyOutputEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the physical layer output.|–|–|Enables or disables the physical layer output.|
|phyOutputSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the physical layer configuration.|–|–|Sets the physical layer information.|
|blackDataSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the black screen.|–|–|Sets the black screen.|
|videoMuteEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the video mute feature.|–|–|Enables or disables the video mute feature.|
|videoPathSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**attr**: pointer to the video path configuration.|–|–|Sets the video path.|
|audioMuteEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the audio mute feature.|–|–|Enables or disables the audio mute feature.|
|avmuteSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the AV mute feature.|–|–|Enables or disables the AV mute feature.|
|ddcTransfer|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**ddcCfg**: pointer to the DDC configuration.|**ddcCfg**: DDC configuration.|HDF_STATUS|Reads and writes data through the DDC.|
|scdcSourceScrambleGet|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|Scrambling status of the source.|Obtains the scrambling status of the source.|
|scdcSourceScrambleSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the scrambling for the source.|–|HDF_STATUS|Enables or disable scrambling for the source.|
|frlEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**enable**: whether to enable the FRL.|–|HDF_STATUS|Enables or disables the FRL.|
|audioNctsSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the N/CTS configuration.|–|HDF_STATUS|Sets the audio N/CTS information.|
|frlTrainingConfigSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**cfg**: pointer to the FRL training configuration.|–|–|Sets FRL training information.|
|frlTrainingStart|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|–|Starts FRL training.|
|frlGetTriningRslt|**cntlr**: structure pointer to an HDMI controller at the core layer.|**rslt**: FRL training result.|–|Obtains the FRL training result.|
|hdcpRegInit|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|–|Initializes registers related to the High-bandwidth Digital Content Protection (HDCP) process.|
|hdcpGenerateAksvAndAn|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|HDF_STATUS|Generates the **Aksv** and **An** in the HDCP process.|
|hdcpOptReg|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**type**: operation type.<br>**data**: register data.<br>**len**: data length.|**data**: register data.|HDF_STATUS|Reads or writes the registers during the HDCP process.|
|hdrTimerSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br>**config**: pointer to the timer configuration|–|–|Sets the HDR-related timer.|
**Table 1** APIs for the members in the HdmiCntlrOps structure
| Method| Input Parameter| Output Parameter| Return Value| Description| ### How to Develop
| ------------------------ | ------------------------------------------------------------ | -------------------------------------- | ------------------ | -------------------------------------------------- |
| hardWareInit | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Initializes HDMI hardware.|
| hardWareStatusGet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br/>| **status**: pointer to the HDMI hardware status.| –| Obtains the HDMI hardware status.|
| controllerReset | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| –| Resets an HDMI controller.|
| hotPlugStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| **bool**: HDMI hot-plug status.| Obtains the HDMI hot-plug status.|
| hotPlugInterruptStateGet | **cntlr**: structure pointer to an HDMI controller at the core layer.| –| **bool**: HDMI hot-plug interrupt status.| Obtains the HDMI hot-plug interrupt status.|
| lowPowerSet | **cntlr**: structure pointer to an HDMI controller at the core layer.<br/>**enable**: whether to enable low power consumption.| –| –| Enables or disables low power consumption.|
| tmdsModeSet | **cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**mode**: TMDS mode.| –| –| Sets the TMDS mode. |
|tmdsConfigSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**mode**: TMDS parameters.|–|HDF_STATUS|Sets TMDS parameters.|
|infoFrameEnable|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**infoFrameType**: packet type.<br/>**enable**: whether to enable infoFrame.|–|–|Enables or disables infoFrame.|
|infoFrameSend|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**infoFrameType**: packet type.<br />**data**: pointer to infoFrame data.<br/>**len**: data length.|–|HDF_STATUS|Sends an infoFrame.|
|cecMsgSend|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**msg**: pointer to the Consumer Electronics Control (CEC) message.|–|HDF_STATUS|Sends a CEC message.|
|audioPathEnable|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**enable**: whether to enable the audio path.|–|–|Enables or disables the audio path.|
|audioPathSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**config**: pointer to the audio path configuration.|–|–|Sets the audio path.|
|phyOutputEnable|**cntlr**: structure pointer to an HDMI controller at the core layer.<br/>**enable**: whether to enable the physical layer output.|–|–|Enables or disables the physical layer output.|
|phyOutputSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**cfg**: pointer to the physical layer configuration.|–|–|Sets the physical layer information.|
|blackDataSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br />**enable**: whether to enable the black screen.|–|–|Sets the black screen.|
|videoMuteEnable|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**enable**: whether to enable the video mute feature.|–|–|Enables or disables the video mute feature.|
|videoPathSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br/>**attr**: pointer to the video path configuration.|–|–|Sets the video path.|
|audioMuteEnable|**cntlr**: structure pointer to an HDMI controller at the core layer. <br />**enable**: whether to enable the audio mute feature.|–|–|Enables or disables the audio mute feature.|
|avmuteSet|**cntlr**: structure pointer to an HDMI controller at the core layer.<br />**enable**: whether to enable the AV mute feature.|–|–|Enables or disables the AV mute feature.|
|ddcTransfer|**cntlr**: structure pointer to an HDMI controller at the core layer. <br /> **ddcCfg**: pointer to the display data channel (DDC) configuration.|**ddcCfg**: DDC configuration.|HDF_STATUS|Reads and writes data through the DDC.|
|scdcSourceScrambleGet|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|Scrambling status of the source.|Obtains the scrambling status of the source.|
|scdcSourceScrambleSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br />**enable**: whether to enable scrambling for the source.|–|HDF_STATUS|Enables or disable scrambling for the source.|
|frlEnable|**cntlr**: structure pointer to an HDMI controller at the core layer. <br />**enable**: whether to enable the fixed rate link (FRL).|–|HDF_STATUS|Enables or disables the FRL.|
|audioNctsSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br /> **cfg**: pointer to the N/CTS configuration.|–|HDF_STATUS|Sets the audio N/CTS information.|
|frlTrainingConfigSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br /> **cfg**: pointer to the FRL training configuration.|–|–|Sets FRL training information.|
|frlTrainingStart|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|–|Starts FRL training.|
|frlGetTriningRslt|**cntlr**: structure pointer to an HDMI controller at the core layer.|**rslt**: FRL training result.|–|Obtains the FRL training result.|
|hdcpRegInit|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|–|Initializes registers related to the High-bandwidth Digital Content Protection (HDCP) process.|
|hdcpGenerateAksvAndAn|**cntlr**: structure pointer to an HDMI controller at the core layer.|–|HDF_STATUS|Generates the **Aksv** and **An** in the HDCP process.|
|hdcpOptReg|**cntlr**: structure pointer to an HDMI controller at the core layer. <br />**type**: operation type. <br />**data**: pointer to the register data. <br />**len**: data length.|**data**: register data.|HDF_STATUS|Reads or writes the registers in the HDCP process.|
|hdrTimerSet|**cntlr**: structure pointer to an HDMI controller at the core layer. <br />**config**: pointer to the timer configuration.|–|–|Sets the HDR-related timer.|
## How to Develop<a name="3"></a>
The HDMI module adaptation involves the following steps: The HDMI module adaptation involves the following steps:
1. Instantiate the driver entry. - Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure. - Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF. - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files. - Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file. - Add the **deviceNode** information to the **device_info.hcs** file.
- (Optional) Add the **hdmi_config.hcs** file. - (Optional) Add the **hdmi_config.hcs** file.
3. Instantiate the HDMI controller object. - Instantiate the HDMI controller object.
- Initialize **HdmiCntlr**. - Initialize **HdmiCntlr**.
- Instantiate **HdmiCntlrOps** in **HdmiCntlr**. For details, see [Available APIs](#available_apis). - Instantiate **HdmiCntlrOps** in **HdmiCntlr**.
## Development Example<a name="4"></a> 1. Instantiate the driver entry.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf\_device\_desc.h**), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke. The driver entry must be a global variable of the **HdfDriverEntry** type (which is defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. Generally, the HDF calls the **Bind()** function and then the **Init()** function to load a driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
HDMI driver entry reference: HDMI driver entry reference:
...@@ -128,7 +154,9 @@ The HDMI module adaptation involves the following steps: ...@@ -128,7 +154,9 @@ The HDMI module adaptation involves the following steps:
HDF_INIT(g_hdmiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF. HDF_INIT(g_hdmiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
``` ```
2. Add **deviceNode** to the **device_info.hcs** file, and configure the device attributes in the **hdmi\_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 restriction ranges of the **HdmiCntlr** members at the core layer. 2. Configure attribute files.
Add **deviceNode** to the **device_info.hcs** file, and configure the device attributes in the **hdmi\_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 restriction ranges of the **HdmiCntlr** members at the core layer.
Configure HDMI controller information from the first node. This node specifies a type of HDMI controllers rather than a specific HDMI controller. In this example, there is only one HDMI controller. If there are multiple HDMI controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **hdmi\_config** file. Configure HDMI controller information from the first node. This node specifies a type of HDMI controllers rather than a specific HDMI controller. In this example, there is only one HDMI controller. If there are multiple HDMI controllers, you need to add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **hdmi\_config** file.
...@@ -200,14 +228,15 @@ The HDMI module adaptation involves the following steps: ...@@ -200,14 +228,15 @@ The HDMI module adaptation involves the following steps:
} }
``` ```
3. Initialize the **HdmiCntlr** object at the core layer, including initializing the vendor custom structure (passing parameters and data) and instantiating the **HdmiCntlrOps** (used to call the underlying functions of the driver). The **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) must be implemented in this step. 3. Instantiate the **HdmiCntlr** object.
- Custom structure reference: Initialize the **HdmiCntlr** object at the core layer, including initializing the vendor custom structure (passing parameters and data) and instantiating the **HdmiCntlrOps** (used to call the underlying functions of the driver). The **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**) must be implemented in this step.
> ![](../public_sys-resources/icon-note.gif) **NOTE** - Custom structure reference
>
> ![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> To the driver, the custom structure carries parameters and data. The values in the **hdmi_config.hcs** file are read by the HDF, and structure members are initialized by **DeviceResourceIface**. Some important values (such as the device number and bus number) are also passed to the **HdmiCntlr** object at the core layer. > To the driver, the custom structure carries parameters and data. The values in the **hdmi_config.hcs** file are read by the HDF, and structure members are initialized by **DeviceResourceIface**. Some important values (such as the device number and bus number) are also passed to the **HdmiCntlr** object at the core layer.
```c ```c
struct HdmiAdapterHost { struct HdmiAdapterHost {
struct HdmiCntlr *cntlr; // (Mandatory) Control object at the core layer. The details are as follows: struct HdmiCntlr *cntlr; // (Mandatory) Control object at the core layer. The details are as follows:
...@@ -216,8 +245,8 @@ The HDMI module adaptation involves the following steps: ...@@ -216,8 +245,8 @@ The HDMI module adaptation involves the following steps:
uint32_t regSize; // (Mandatory) Register bit width. uint32_t regSize; // (Mandatory) Register bit width.
uint32_t irqNum; // (Mandatory) IRQ number. uint32_t irqNum; // (Mandatory) IRQ number.
}; };
/* HdmiCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function. */ /* HdmiCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init() function. */
struct HdmiCntlr { struct HdmiCntlr {
struct IDeviceIoService service; struct IDeviceIoService service;
struct HdfDeviceObject *hdfDevObj; struct HdfDeviceObject *hdfDevObj;
...@@ -242,9 +271,9 @@ The HDMI module adaptation involves the following steps: ...@@ -242,9 +271,9 @@ The HDMI module adaptation involves the following steps:
void *priv; void *priv;
}; };
``` ```
- **(Important)** Instantiate the callback structure **HdmiCntlrOps** in **HdmiCntlr**. - Instantiate **HdmiCntlrOps** in **HdmiCntlr**.
```c ```c
static struct HdmiCntlrOps g_hdmiAdapterHostOps = { static struct HdmiCntlrOps g_hdmiAdapterHostOps = {
.hardWareInit = HdmiAdapterHardWareInit, .hardWareInit = HdmiAdapterHardWareInit,
...@@ -283,29 +312,29 @@ The HDMI module adaptation involves the following steps: ...@@ -283,29 +312,29 @@ The HDMI module adaptation involves the following steps:
.hdrTimerSet = HdmiAdapterHdrTimerSet, .hdrTimerSet = HdmiAdapterHdrTimerSet,
}; };
``` ```
- **Bind** function - **Bind()** function
> Input parameter: **Input parameter**:
> **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
>
> Return value: **Return value**:
> **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** definition in the **/drivers/framework/include/utils/hdf\_base.h file**.) **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** definition in the **/drivers/framework/include/utils/hdf\_base.h file**.)
|State|Description| | State | Description |
|:-|:-| |:-|:-|
|HDF_ERR_INVALID_OBJECT|Invalid controller object.| |HDF_ERR_INVALID_OBJECT|Invalid controller object.|
|HDF_ERR_INVALID_PARAM |Invalid parameter.| |HDF_ERR_INVALID_PARAM|Invalid parameter.|
|HDF_ERR_MALLOC_FAIL |Failed to allocate memory.| |HDF_ERR_MALLOC_FAIL |Memory allocation failed.|
|HDF_ERR_IO |I/O error.| |HDF_ERR_IO |I/O error.|
|HDF_SUCCESS |Transmission successful.| |HDF_SUCCESS |Transmission successful.|
|HDF_FAILURE |Transmission failed.| |HDF_FAILURE |Transmission failed.|
> Function description: **Function description**:
> Initializes the custom structure object **HdmiAdapterHost** and **HdmiCntlr**, and calls the **HdmiCntlrAdd** function to add the HDMI controller to the core layer. Initializes the custom structure object **HdmiAdapterHost** and **HdmiCntlr**, and calls the **HdmiCntlrAdd** function to add the HDMI controller to the core layer.
>
> The **HdmiCntlr**, **HdmiAdapterHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully. The **HdmiCntlr**, **HdmiAdapterHost**, and **HdfDeviceObject** assign values with each other so that other functions can be converted successfully.
```c ```c
static int32_t HdmiAdapterBind(struct HdfDeviceObject *obj) static int32_t HdmiAdapterBind(struct HdfDeviceObject *obj)
{ {
...@@ -342,45 +371,47 @@ The HDMI module adaptation involves the following steps: ...@@ -342,45 +371,47 @@ The HDMI module adaptation involves the following steps:
return ret; return ret;
} }
``` ```
- **Init** function - **Init()** function
>Input parameter: **Input parameter**:
>**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
>
>Return value: **Return value**:
>HDF_STATUS HDF_STATUS
>
>Function description: **Function description**:
>
>Implements the **HdmiAdapterInit** function. Implements the **HdmiAdapterInit** function.
```c ```c
static int32_t HdmiAdapterInit(struct HdfDeviceObject *obj) static int32_t HdmiAdapterInit(struct HdfDeviceObject *obj)
{ {
return HDF_SUCCESS; return HDF_SUCCESS;
} }
``` ```
- **Release** function - **Release()** function
> Input parameter: **Input parameter**:
> **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
>
> Return value: **Return value**:
>
>
> Function description: **Function description**:
> Releases the memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. Releases the memory and deletes the controller. This function assigns a value to the **Release()** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources.
```c ```c
static void HdmiAdapterRelease(struct HdfDeviceObject *obj) static void HdmiAdapterRelease(struct HdfDeviceObject *obj)
{ {
struct HdmiCntlr *cntlr = NULL; struct HdmiCntlr *cntlr = NULL;
... ...
cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to HdmiCntlr by using service. For details about the value assignment, see the Bind function. cntlr = (struct MmcCntlr *)obj->service;// Forcibly convert HdfDeviceObject to HdmiCntlr by using service. For details about the value assignment, see the Bind() function.
... ...
HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// Memory release function customized by the vendor. A forced conversion from HdmiCntlr to HimciAdapterHost is involved in the process. HimciDeleteHost((struct HimciAdapterHost *)cntlr->priv);// Memory release function customized by the vendor. A forced conversion from HdmiCntlr to HimciAdapterHost is involved in the process.
} }
``` ```
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Init** function has the corresponding value assignment operations.
> ![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> All forced conversion operations for obtaining the corresponding object can be successful only when the **Init()** function has the corresponding value assignment operations.
...@@ -225,7 +225,7 @@ if (ret != 2) { ...@@ -225,7 +225,7 @@ if (ret != 2) {
} }
``` ```
>![](./public_sys-resources/icon-caution.gif) **Caution** >![](../public_sys-resources/icon-caution.gif) **Caution**
> >
>- The device address in the **I3cMsg** structure does not contain the read/write flag bit. The read/write information is passed by the read/write control bit in the member variable **flags**. >- The device address in the **I3cMsg** structure does not contain the read/write flag bit. The read/write information is passed by the read/write control bit in the member variable **flags**.
>- The **I3cTransfer()** function does not limit the number of message structures or the length of data in each message structure. The I3C controller determines these two limits. >- The **I3cTransfer()** function does not limit the number of message structures or the length of data in each message structure. The I3C controller determines these two limits.
......
...@@ -164,9 +164,9 @@ The I3C module adaptation involves the following steps: ...@@ -164,9 +164,9 @@ The I3C module adaptation involves the following steps:
```c ```c
struct VirtualI3cCntlr { struct VirtualI3cCntlr {
struct AdcDevice device;// (Mandatory) Control object at the core layer. For details, see the following description of I3cCntlr. struct I3cCntlr cntlr; // (Mandatory) Control object at the core layer. For details, see the following description of I3cCntlr.
volatile unsigned char *regBase;// (Mandatory) Register base address. volatile unsigned char *regBase;// (Mandatory) Register base address.
uint32_t regBasePhy; // (Mandatory) Physical base address of the register. uint32_t regBasePhy; // (Mandatory) Physical base address of the register.
uint32_t regSize; // (Mandatory) Bit width of the register. uint32_t regSize; // (Mandatory) Bit width of the register.
uint16_t busId; // (Mandatory) Device number. uint16_t busId; // (Mandatory) Device number.
uint16_t busMode; uint16_t busMode;
......
# MIPI CSI<a name="EN-US_TOPIC_0000001198067744"></a>
## Overview<a name="section72226945170128"></a>
Defined by the Mobile Industry Processor Interface \(MIPI\) Alliance, the Camera Serial Interface \(CSI\) is a specification that allows data to be transmitted from the camera to the host processor on mobile platforms. In the Hardware Driver Foundation \(HDF\), the MIPI CSI 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 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="fig260692723120"></a>
![](figures/service-free-mode.png "Service-free mode")
## Available APIs<a name="section735525713405"></a>
MipiCsiCntlrMethod:
```
struct MipiCsiCntlrMethod {
int32_t (*setComboDevAttr)(struct MipiCsiCntlr *cntlr, ComboDevAttr *pAttr);
int32_t (*setPhyCmvmode)(struct MipiCsiCntlr *cntlr, uint8_t devno, PhyCmvMode cmvMode);
int32_t (*setExtDataType)(struct MipiCsiCntlr *cntlr, ExtDataType* dataType);
int32_t (*setHsMode)(struct MipiCsiCntlr *cntlr, LaneDivideMode laneDivideMode);
int32_t (*enableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
int32_t (*disableClock)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
int32_t (*resetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
int32_t (*unresetRx)(struct MipiCsiCntlr *cntlr, uint8_t comboDev);
int32_t (*enableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource);
int32_t (*disableSensorClock)(struct MipiCsiCntlr *cntlr, uint8_t snsClkSource);
int32_t (*resetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
int32_t (*unresetSensor)(struct MipiCsiCntlr *cntlr, uint8_t snsResetSource);
};
```
**Table 1** Callbacks for the members in the MipiCsiCntlrMethod structure
<a name="table1233500677170128"></a>
<table><thead align="left"><tr id="row1000451054170128"><th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.1"><p id="entry1111988081170128p0"><a name="entry1111988081170128p0"></a><a name="entry1111988081170128p0"></a>Callback</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.2"><p id="entry1314377643170128p0"><a name="entry1314377643170128p0"></a><a name="entry1314377643170128p0"></a>Input Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.3"><p id="entry102571833170128p0"><a name="entry102571833170128p0"></a><a name="entry102571833170128p0"></a>Output Parameter</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.4"><p id="entry259883708170128p0"><a name="entry259883708170128p0"></a><a name="entry259883708170128p0"></a>Return Value</p>
</th>
<th class="cellrowborder" valign="top" width="20%" id="mcps1.2.6.1.5"><p id="entry1719007141170128p0"><a name="entry1719007141170128p0"></a><a name="entry1719007141170128p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row893348241170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry2092857420170128p0"><a name="entry2092857420170128p0"></a><a name="entry2092857420170128p0"></a>setComboDevAttr</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p155578927170128"><a name="p155578927170128"></a><a name="p155578927170128"></a><strong id="b2983104693117"><a name="b2983104693117"></a><a name="b2983104693117"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p534134719170128"><a name="p534134719170128"></a><a name="p534134719170128"></a><strong id="b717683263220"><a name="b717683263220"></a><a name="b717683263220"></a>pAttr</strong>: structure pointer to the configuration structure of the MIPI CSI.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1300850044170128p0"><a name="entry1300850044170128p0"></a><a name="entry1300850044170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1079550609170128p0"><a name="entry1079550609170128p0"></a><a name="entry1079550609170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1104973652170128p0"><a name="entry1104973652170128p0"></a><a name="entry1104973652170128p0"></a>Sets the MIPI-CSI configuration.</p>
</td>
</tr>
<tr id="row1236584443170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1263277119170128p0"><a name="entry1263277119170128p0"></a><a name="entry1263277119170128p0"></a>setPhyCmvmode</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p548503413170128"><a name="p548503413170128"></a><a name="p548503413170128"></a><strong id="b33316314348"><a name="b33316314348"></a><a name="b33316314348"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1389106408170128"><a name="p1389106408170128"></a><a name="p1389106408170128"></a><strong id="b7288183093611"><a name="b7288183093611"></a><a name="b7288183093611"></a>devno</strong>: Device ID, which is of the uint8_t type.</p>
<p id="p118314402170128"><a name="p118314402170128"></a><a name="p118314402170128"></a><strong id="b1347113393714"><a name="b1347113393714"></a><a name="b1347113393714"></a>cmvMode</strong>: common-mode voltage (CMV) mode.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry886884421170128p0"><a name="entry886884421170128p0"></a><a name="entry886884421170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1542733203170128p0"><a name="entry1542733203170128p0"></a><a name="entry1542733203170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1506663070170128p0"><a name="entry1506663070170128p0"></a><a name="entry1506663070170128p0"></a>Sets the CMV mode.</p>
</td>
</tr>
<tr id="row1486148936170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1589217404170128p0"><a name="entry1589217404170128p0"></a><a name="entry1589217404170128p0"></a>setExtDataType</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p114389566170128"><a name="p114389566170128"></a><a name="p114389566170128"></a><strong id="b34053117344"><a name="b34053117344"></a><a name="b34053117344"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p996608377170128"><a name="p996608377170128"></a><a name="p996608377170128"></a><strong id="b784685684412"><a name="b784685684412"></a><a name="b784685684412"></a>dataType</strong>: structure pointer to the data that defines the YUV, original data formats, and bit depth.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry378080489170128p0"><a name="entry378080489170128p0"></a><a name="entry378080489170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry851136224170128p0"><a name="entry851136224170128p0"></a><a name="entry851136224170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1309676064170128p0"><a name="entry1309676064170128p0"></a><a name="entry1309676064170128p0"></a>Sets the YUV, RAW data format, and bit depth.</p>
</td>
</tr>
<tr id="row692364909170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1017488702170128p0"><a name="entry1017488702170128p0"></a><a name="entry1017488702170128p0"></a>setHsMode</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1054266120170128"><a name="p1054266120170128"></a><a name="p1054266120170128"></a><strong id="b144183117349"><a name="b144183117349"></a><a name="b144183117349"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1574674418170128"><a name="p1574674418170128"></a><a name="p1574674418170128"></a><strong id="b18748194155516"><a name="b18748194155516"></a><a name="b18748194155516"></a>laneDivideMode</strong>: lane mode.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1749069145170128p0"><a name="entry1749069145170128p0"></a><a name="entry1749069145170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1237801346170128p0"><a name="entry1237801346170128p0"></a><a name="entry1237801346170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1643965522170128p0"><a name="entry1643965522170128p0"></a><a name="entry1643965522170128p0"></a>Sets the MIPI RX lane distribution.</p>
</td>
</tr>
<tr id="row1437392211170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry80806261170128p0"><a name="entry80806261170128p0"></a><a name="entry80806261170128p0"></a>enableClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p867235167170128"><a name="p867235167170128"></a><a name="p867235167170128"></a><strong id="b94263116342"><a name="b94263116342"></a><a name="b94263116342"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1770663973170128"><a name="p1770663973170128"></a><a name="p1770663973170128"></a><strong id="b1342116531004"><a name="b1342116531004"></a><a name="b1342116531004"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry836736200170128p0"><a name="entry836736200170128p0"></a><a name="entry836736200170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry918324954170128p0"><a name="entry918324954170128p0"></a><a name="entry918324954170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry373275246170128p0"><a name="entry373275246170128p0"></a><a name="entry373275246170128p0"></a>Enables the MIPI clock.</p>
</td>
</tr>
<tr id="row1944617165170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry1879109927170128p0"><a name="entry1879109927170128p0"></a><a name="entry1879109927170128p0"></a>disableClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p252627163170128"><a name="p252627163170128"></a><a name="p252627163170128"></a><strong id="b343103114343"><a name="b343103114343"></a><a name="b343103114343"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p573650189170128"><a name="p573650189170128"></a><a name="p573650189170128"></a><strong id="b1747970172618"><a name="b1747970172618"></a><a name="b1747970172618"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry8107921170128p0"><a name="entry8107921170128p0"></a><a name="entry8107921170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry349207958170128p0"><a name="entry349207958170128p0"></a><a name="entry349207958170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry693552037170128p0"><a name="entry693552037170128p0"></a><a name="entry693552037170128p0"></a>Disables the MIPI clock.</p>
</td>
</tr>
<tr id="row168452313170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry536818735170128p0"><a name="entry536818735170128p0"></a><a name="entry536818735170128p0"></a>resetRx</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1214231503170128"><a name="p1214231503170128"></a><a name="p1214231503170128"></a><strong id="b1043031153417"><a name="b1043031153417"></a><a name="b1043031153417"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p104793304170128"><a name="p104793304170128"></a><a name="p104793304170128"></a><strong id="b597920533269"><a name="b597920533269"></a><a name="b597920533269"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry349755171170128p0"><a name="entry349755171170128p0"></a><a name="entry349755171170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry608378681170128p0"><a name="entry608378681170128p0"></a><a name="entry608378681170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1692819512170128p0"><a name="entry1692819512170128p0"></a><a name="entry1692819512170128p0"></a>Resets the MIPI RX.</p>
</td>
</tr>
<tr id="row812174477170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry677771062170128p0"><a name="entry677771062170128p0"></a><a name="entry677771062170128p0"></a>unresetRx</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1883220887170128"><a name="p1883220887170128"></a><a name="p1883220887170128"></a><strong id="b1202156153016"><a name="b1202156153016"></a><a name="b1202156153016"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p114324757170128"><a name="p114324757170128"></a><a name="p114324757170128"></a><strong id="b105520153110"><a name="b105520153110"></a><a name="b105520153110"></a>comboDev</strong>: channel ID, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry2088687179170128p0"><a name="entry2088687179170128p0"></a><a name="entry2088687179170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry250678538170128p0"><a name="entry250678538170128p0"></a><a name="entry250678538170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry1714667992170128p0"><a name="entry1714667992170128p0"></a><a name="entry1714667992170128p0"></a>Deasserts the reset of the MIPI RX.</p>
</td>
</tr>
<tr id="row1282919412170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry204916079170128p0"><a name="entry204916079170128p0"></a><a name="entry204916079170128p0"></a>enableSensorClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p217879421170128"><a name="p217879421170128"></a><a name="p217879421170128"></a><strong id="b197181237203211"><a name="b197181237203211"></a><a name="b197181237203211"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p2098908158170128"><a name="p2098908158170128"></a><a name="p2098908158170128"></a><strong id="b12861154993218"><a name="b12861154993218"></a><a name="b12861154993218"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1290595383170128p0"><a name="entry1290595383170128p0"></a><a name="entry1290595383170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1313850176170128p0"><a name="entry1313850176170128p0"></a><a name="entry1313850176170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry384362703170128p0"><a name="entry384362703170128p0"></a><a name="entry384362703170128p0"></a>Enables the MIPI sensor clock.</p>
</td>
</tr>
<tr id="row1992432516170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry980444503170128p0"><a name="entry980444503170128p0"></a><a name="entry980444503170128p0"></a>disableSensorClock</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1996780281170128"><a name="p1996780281170128"></a><a name="p1996780281170128"></a><strong id="b4445316347"><a name="b4445316347"></a><a name="b4445316347"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p2021170726170128"><a name="p2021170726170128"></a><a name="p2021170726170128"></a><strong id="b17971423820"><a name="b17971423820"></a><a name="b17971423820"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1694413990170128p0"><a name="entry1694413990170128p0"></a><a name="entry1694413990170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry1647081928170128p0"><a name="entry1647081928170128p0"></a><a name="entry1647081928170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry2011696236170128p0"><a name="entry2011696236170128p0"></a><a name="entry2011696236170128p0"></a>Disables the MIPI sensor clock.</p>
</td>
</tr>
<tr id="row1739370133170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry386036597170128p0"><a name="entry386036597170128p0"></a><a name="entry386036597170128p0"></a>resetSensor</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p1065048089170128"><a name="p1065048089170128"></a><a name="p1065048089170128"></a><strong id="b19451631183417"><a name="b19451631183417"></a><a name="b19451631183417"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p998202090170128"><a name="p998202090170128"></a><a name="p998202090170128"></a><strong id="b10443111911384"><a name="b10443111911384"></a><a name="b10443111911384"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry173182567170128p0"><a name="entry173182567170128p0"></a><a name="entry173182567170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry879245456170128p0"><a name="entry879245456170128p0"></a><a name="entry879245456170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry944835652170128p0"><a name="entry944835652170128p0"></a><a name="entry944835652170128p0"></a>Resets the sensor.</p>
</td>
</tr>
<tr id="row1197566339170128"><td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.1 "><p id="entry363281016170128p0"><a name="entry363281016170128p0"></a><a name="entry363281016170128p0"></a>unresetSensor</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.2 "><p id="p416483731170128"><a name="p416483731170128"></a><a name="p416483731170128"></a><strong id="b178488417385"><a name="b178488417385"></a><a name="b178488417385"></a>cntlr</strong>: structure pointer to the MIPI CSI controller.</p>
<p id="p1988272362170128"><a name="p1988272362170128"></a><a name="p1988272362170128"></a><strong id="b6353246183818"><a name="b6353246183818"></a><a name="b6353246183818"></a>snsClkSource</strong>: number of the clock signal cable of the sensor, which is of the uint8_t type.</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.3 "><p id="entry1658055665170128p0"><a name="entry1658055665170128p0"></a><a name="entry1658055665170128p0"></a></p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.4 "><p id="entry2142771023170128p0"><a name="entry2142771023170128p0"></a><a name="entry2142771023170128p0"></a>HDF_STATUS</p>
</td>
<td class="cellrowborder" valign="top" width="20%" headers="mcps1.2.6.1.5 "><p id="entry791107803170128p0"><a name="entry791107803170128p0"></a><a name="entry791107803170128p0"></a>Deasserts the reset of a sensor.</p>
</td>
</tr>
</tbody>
</table>
## How to Develop<a name="section378858277170128"></a>
The MIPI CSI module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF\_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device\_info.hcs** file.
- \(Optional\) Add the **mipicsi\_config.hcs** file.
3. Instantiate the MIPI CSI controller object.
- Initialize **MipiCsiCntlr**.
- Instantiate **MipiCsiCntlrMethod** in the **MipiCsiCntlr** object.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>For details, see [Available APIs](#section735525713405).
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.
## Development Example<a name="section2049027816170128"></a>
The following uses **mipi\_rx\_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 **busxx\_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 **MipiCsiCntlr** members at the core layer. The **deviceNode** information is related to the driver entry registration.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>In this example, the MIPI controller attributes are defined in the source file. If required, add the **deviceMatchAttr** information to **deviceNode** in the **device\_info** file and add the** mipicsi\_config.hcs** file.
**device\_info.hcs** configuration reference:
```
root {
device_info {
match_attr = "hdf_manager";
platform :: host {
hostName = "platform_host";
priority = 50;
device_mipi_csi:: device {
device0 :: deviceNode {
policy = 0;
priority = 160;
permission = 0644;
moduleName = "HDF_MIPI_RX"; // (Mandatory) Driver name, which must be the same as the moduleName in the driver entry.
serviceName = "HDF_MIPI_RX";// (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, the start address of each **HdfDriverEntry** object of all loaded drivers is collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Bind** function and then the **Init** function to load a driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit.
MIPI CSI driver entry reference:
```
struct HdfDriverEntry g_mipiCsiDriverEntry = {
.moduleVersion = 1,
.Init = Hi35xxMipiCsiInit, // See the Init function.
.Release = Hi35xxMipiCsiRelease, //See the Release function.
.moduleName = "HDF_MIPI_RX", // (Mandatory) The value must be the same as that in the device_info.hcs file.
};
HDF_INIT(g_mipiCsiDriverEntry); // Call HDF_INIT to register the driver entry with the HDF.
```
3. Initialize the **MipiCsiCntlr** object at the core layer, including initializing the vendor custom structure \(passing parameters and data\), instantiating **MipiCsiCntlrMethod** \(used to call underlying functions of the driver\) in **MipiCsiCntlr**, and implementing the **HdfDriverEntry** member functions \(**Bind**, **Init**, and **Release**\).
- Custom structure reference:
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>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 CSI attributes are defined in the source file. Therefore, the basic member structure is similar to that of **MipiCsiCntlr**.
```
typedef struct {
/** Data type: 8-bit, 10-bit, 12-bit, 14-bit, or 16-bit */
DataType inputDataType;
/** MIPI WDM mode */
MipiWdrMode wdrMode;
/** laneId: -1 - disabled */
short laneId[MIPI_LANE_NUM];
union {
/** Used for HI_MIPI_WDR_MODE_DT */
short dataType[WDR_VC_NUM];
};
} MipiDevAttr;
typedef struct {
/** Device number. */
uint8_t devno;
/** Input mode, which can be MIPI, LVDS, sub-LVDS, HiSPi, or DC. */
InputMode inputMode;
MipiDataRate dataRate;
/** Crop area of the MIPI RX device (same as the size of the input image of the sensor). */
ImgRect imgRect;
union {
MipiDevAttr mipiAttr;
LvdsDevAttr lvdsAttr;
};
} ComboDevAttr;
// MipiCsiCntlr is the core layer controller structure. Its members are assigned with values by using the Init function.
struct MipiCsiCntlr {
/** Send the service provided by this controller when the driver is bound to the HDF. */
struct IDeviceIoService service;
/** Pass the pointer to the device when the driver is bound to the HDF. */
struct HdfDeviceObject *device;
/** Device number */
unsigned int devNo;
/** All APIs provided by the controller */
struct MipiCsiCntlrMethod *ops;
/** All APIs for controller debugging. Set it to null if the driver is not implemented. */
struct MipiCsiCntlrDebugMethod *debugs;
/** Controller context variable. */
MipiDevCtx ctx;
/** Spinlock used when the controller context variable is accessed. */
OsalSpinlock ctxLock;
/** Lock method when the controller is managed */
struct OsalMutex lock;
/** Pointer to anonymous data, which is used to store the CSI device structure */
void *priv;
};
```
- **\(Important\)** Instantiate the callback function structure **MipiCsiCntlrMethod** in **MipiCsiCntlr**. Other members are initialized by using the **Init** function.
```
static struct MipiCsiCntlrMethod g_method = {
.setComboDevAttr = Hi35xxSetComboDevAttr,
.setPhyCmvmode = Hi35xxSetPhyCmvmode,
.setExtDataType = Hi35xxSetExtDataType,
.setHsMode = Hi35xxSetHsMode,
.enableClock = Hi35xxEnableClock,
.disableClock = Hi35xxDisableClock,
.resetRx = Hi35xxResetRx,
.unresetRx = Hi35xxUnresetRx,
.enableSensorClock = Hi35xxEnableSensorClock,
.disableSensorClock = Hi35xxDisableSensorClock,
.resetSensor = Hi35xxResetSensor,
.unresetSensor = Hi35xxUnresetSensor
};
```
- 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="table683892652170128"></a>
<table><thead align="left"><tr id="row466801181170128"><th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.1"><p id="entry433041536170128p0"><a name="entry433041536170128p0"></a><a name="entry433041536170128p0"></a>Status (Value)</p>
</th>
<th class="cellrowborder" valign="top" width="50%" id="mcps1.1.3.1.2"><p id="entry1260647143170128p0"><a name="entry1260647143170128p0"></a><a name="entry1260647143170128p0"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row2053721693170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry772353853170128p0"><a name="entry772353853170128p0"></a><a name="entry772353853170128p0"></a>HDF_ERR_INVALID_OBJECT</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry891453569170128p0"><a name="entry891453569170128p0"></a><a name="entry891453569170128p0"></a>Invalid object</p>
</td>
</tr>
<tr id="row1654561941170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1037876509170128p0"><a name="entry1037876509170128p0"></a><a name="entry1037876509170128p0"></a>HDF_ERR_MALLOC_FAIL</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1354763041170128p0"><a name="entry1354763041170128p0"></a><a name="entry1354763041170128p0"></a>Failed to allocate memory</p>
</td>
</tr>
<tr id="row515913237170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1517991694170128p0"><a name="entry1517991694170128p0"></a><a name="entry1517991694170128p0"></a>HDF_ERR_INVALID_PARAM</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry784824354170128p0"><a name="entry784824354170128p0"></a><a name="entry784824354170128p0"></a>Invalid parameter</p>
</td>
</tr>
<tr id="row1055228061170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry771111180170128p0"><a name="entry771111180170128p0"></a><a name="entry771111180170128p0"></a>HDF_ERR_IO</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1302592910170128p0"><a name="entry1302592910170128p0"></a><a name="entry1302592910170128p0"></a>I/O error</p>
</td>
</tr>
<tr id="row1131544928170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry1360197988170128p0"><a name="entry1360197988170128p0"></a><a name="entry1360197988170128p0"></a>HDF_SUCCESS</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry1609403118170128p0"><a name="entry1609403118170128p0"></a><a name="entry1609403118170128p0"></a>Operation successful</p>
</td>
</tr>
<tr id="row1247344727170128"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.1 "><p id="entry816278864170128p0"><a name="entry816278864170128p0"></a><a name="entry816278864170128p0"></a>HDF_FAILURE</p>
</td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.1.3.1.2 "><p id="entry814861870170128p0"><a name="entry814861870170128p0"></a><a name="entry814861870170128p0"></a>Operation failed</p>
</td>
</tr>
</tbody>
</table>
Function description:
Connects to the **MipiCsiCntlrMethod** instance, calls **MipiCsiRegisterCntlr**, and performs other vendor-defined initialization operations.
```
static int32_t Hi35xxMipiCsiInit(struct HdfDeviceObject *device)
{
int32_t ret;
HDF_LOGI("%s: enter!", __func__);
g_mipiCsi.priv = NULL; // g_mipiTx is a global variable defined.
//static struct MipiCsiCntlr g_mipiCsi = {
//.devNo = 0
//};
g_mipiCsi.ops = &g_method; // Connect to the MipiCsiCntlrMethod instance.
#ifdef CONFIG_HI_PROC_SHOW_SUPPORT
g_mipiCsi.debugs = &g_debugMethod;
#endif
ret = MipiCsiRegisterCntlr(&g_mipiCsi, device); // (Mandatory) Call the function at the core layer and g_mipiTx to initialize global variables at the core layer.
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiCsiRegisterCntlr] failed!", __func__);
return ret;
}
ret = MipiRxDrvInit(); // (Mandatory) Device initialization customized by the vendor.
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiRxDrvInit] failed.", __func__);
return ret;
}
#ifdef MIPICSI_VFS_SUPPORT
ret = MipiCsiDevModuleInit(g_mipiCsi.devNo);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: [MipiCsiDevModuleInit] failed!", __func__);
return ret;
}
#endif
OsalSpinInit(&g_mipiCsi.ctxLock);
HDF_LOGI("%s: load mipi csi driver success!", __func__);
return ret;
}
// mipi_csi_core.c, core layer file.
int32_t MipiCsiRegisterCntlr(struct MipiCsiCntlr *cntlr, struct HdfDeviceObject *device)
{
...
// Define the global variable static struct MipiCsiHandle g_mipiCsihandle[MAX_CNTLR_CNT];
if (g_mipiCsihandle[cntlr->devNo].cntlr == NULL) {
(void)OsalMutexInit(&g_mipiCsihandle[cntlr->devNo].lock);
(void)OsalMutexInit(&(cntlr->lock));
g_mipiCsihandle[cntlr->devNo].cntlr = cntlr; // Initialize MipiCsiHandle.
g_mipiCsihandle[cntlr->devNo].priv = NULL;
cntlr->device = device; // Enable conversion between HdfDeviceObject and MipiCsiHandle.
device->service = &(cntlr->service); // Enable conversion between HdfDeviceObject and MipiCsiHandle.
cntlr->priv = NULL;
HDF_LOGI("%s: success.", __func__);
return HDF_SUCCESS;
}
HDF_LOGE("%s: cntlr already exists.", __func__);
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 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 Hi35xxMipiCsiRelease(struct HdfDeviceObject *device)
{
struct MipiCsiCntlr *cntlr = NULL;
...
cntlr = MipiCsiCntlrFromDevice(device); // A forced conversion from HdfDeviceObject to MipiCsiCntlr is involved.
//return (device == NULL) ? NULL : (struct MipiCsiCntlr *)device->service;
...
OsalSpinDestroy(&cntlr->ctxLock);
#ifdef MIPICSI_VFS_SUPPORT
MipiCsiDevModuleExit(cntlr->devNo);
#endif
MipiRxDrvExit(); // (Mandatory) Release the resources occupied by the vendor's devices.
MipiCsiUnregisterCntlr(&g_mipiCsi); // Null function
g_mipiCsi.priv = NULL;
HDF_LOGI("%s: unload mipi csi driver success!", __func__);
}
```
# Pin
## Overview<a name="section1"></a>
### Pin<a name="section2"></a>
- The pin, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function.
- The pin module defines a set of common methods for managing pins, including:
- Obtaining or releasing the pin description handle: The kernel compares the pin name passed in with the pin names of each controller in the linked list. If a match is found, a pin description handle is obtained. After the operation on the pin is complete, the pin description handle will be released.
- Setting or obtaining the pull type of a pin: The pull type can be pull-up, pull-down, or floating.
- Setting or obtaining the pull strength of a pin: You can set the pull strength as required.
- Setting or obtaining the functions of a pin to implement pin multiplexing
### Basic Concepts<a name="section3"></a>
Pin, as a software concept, provides APIs for uniformly managing the pins from different SoC vendors, providing the pin multiplexing function, and configuring the electrical features of pins.
- SoC
An SOC is a chip that integrates microprocessors, analog IP cores, digital IP cores, and memory for specific purposes.
- Pin multiplexing
When the number of pins of a chip cannot handle the increasing connection requests, you can set the software registers to make the pins to work in different states.
### Working Principles<a name="section4"></a>
In the HDF, the pin module does not support the user mode and therefore does not need to publish services. It uses the service-free mode in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
The pin module is divided into the following layers:
- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks.
- Adaptation layer: instantiates hooks to implement specific functions.
**Figure 1** Service-free mode<a name="fig14423182615525"></a>
![](figures/service-free-mode.png "pin service-free mode")
### Constraints<a name="section5"></a>
Currently, the pin module supports only the kernels (LiteOS) of mini and small systems.
## Usage Guidelines<a name="section6"></a>
### When to Use<a name="7"></a>
The pin module is a software concept and is used to manage pin resources. You can set the functions, pull type, and pull strength of pins to implement pin multiplexing.
### Available APIs<a name="section8"></a>
The table below describes the APIs of the pin module. For more details, see API Reference.
**Table 1** Pin driver APIs
<a name="table1"></a>
| **API** | **Description** |
| ------------------------------------------------------------ | ---------------- |
| DevHandle PinGet(const char *pinName); | Obtains the pin description handle.|
| void PinPut(DevHandle handle); | Releases the pin description handle.|
| int32_t PinSetPull(DevHandle handle, enum PinPullType pullType); | Sets the pull type of a pin.|
| int32_t PinGetPull(DevHandle handle, enum PinPullType *pullType); | Obtains the pull type of a pin.|
| int32_t PinSetStrength(DevHandle handle, uint32_t strength); | Sets the pull strength of a pin.|
| int32_t PinGetStrength(DevHandle handle, uint32_t *strength); | Obtains the pull strength of a pin.|
| int32_t PinSetFunc(DevHandle handle, const char *funcName); | Sets the pin function. |
| int32_t PinGetFunc(DevHandle handle, const char **funcName); | Obtains the pin functions. |
>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
>All APIs described in this document can be called only in the kernel space.
### How to Develop<a name="section9"></a>
The figure below shows the process.
**Figure 2** Process of using the pin module<a name="fig2"></a>
![](figures/process-of-using-pin.png "Process of using the pin module")
#### Obtaining the Pin Description Handle
Before performing an operation on a pin, call **PinGet** to obtain the pin description handle. This API returns the pin description handle that matches the input pin name.
```
DevHandle PinGet(const char *pinName);
```
**Table 2** Description of PinGet
<a name="table2"></a>
| Parameter | Description |
| ---------- | ----------------------- |
| pinName | Pointer to the pin name. |
| **Return Value**| **Description** |
| NULL | Failed to obtain the pin description handle.|
| handle | Pin description handle obtained. |
Example: Obtain the handle of P18.
```
DevHandle handle = NULL; /* Pin description handle */
char pinName = "P18"; /* Pin name. */
handle = PinGet(pinName);
if (handle == NULL) {
HDF_LOGE("PinGet: get handle failed!\n");
return;
}
```
#### Setting the Pull Type of a Pin
Call **PinSetPull** to set the pull type of a pin.
```
int32_t PinSetPull(DevHandle handle, enum PinPullType pullType);
```
**Table 3** Description of PinSetPull
<a name="table3"></a>
| Parameter | Description |
| ---------- | ----------------------- |
| handle | Pin description handle. |
| pullType | Pull type to set. |
| **Return Value**| **Description** |
| 0 | The operation is successful.|
| Negative value | The operation fails.|
Example: Set the pull type to pull-up.
```
int32_t ret;
enum PinPullType pullTypeNum;
/* Set the pull type of a pin. */
pullTypeNum = 1;
ret = PinSetPull(handle, pullTypeNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinSetPull: failed, ret %d\n", ret);
return ret;
}
```
#### Obtaining the Pull Type of a Pin
Call **PinGetPull** to obtain the pull type of a pin.
```
int32_t PinGetPull(DevHandle handle, enum PinPullType *pullType);
```
**Table 4** Description of PinGetPull
<a name="table4"></a>
| Parameter | Description |
| ---------- | ------------------------- |
| handle | Pin description handle. |
| pullType | Pointer to the pull type obtained.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
Example: Obtain the pull type of a pin.
```
int32_t ret;
enum PinPullType pullTypeNum;
/* Obtain the pull type of a pin. */
ret = PinGetPull(handle, &pullTypeNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetPull: failed, ret %d\n", ret);
return ret;
}
```
#### Setting the Pull Strength of a Pin
Call **PinSetStrength** to set the pull type of a pin.
```
int32_t PinSetStrength(DevHandle handle, uint32_t strength);
```
**Table 5** Description of PinSetStrength
<a name="table5"></a>
| Parameter | Description |
| ---------- | ----------------------- |
| handle | Pin description handle. |
| strength | Pull strength to set. |
| **Return Value**| **Description** |
| 0 | The operation is successful.|
| Negative value | The operation fails.|
Example: Set the pull strength of the pin to 2.
```
int32_t ret;
uint32_t strengthNum;
/* Set the pull strength of the pin. */
strengthNum = 2;
ret = PinSetStrength(handle, strengthNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinSetStrength: failed, ret %d\n", ret);
return ret;
}
```
#### Obtaining the Pull Strength of a Pin
Call **PinGetStrength** to obtain the pull strength set.
```
int32_t PinGetStrength(DevHandle handle, uint32_t *strength);
```
**Table 6** Description of PinGetStrength
<a name="table6"></a>
| Parameter | Description |
| ---------- | ------------------------- |
| handle | Pin description handle. |
| strength | Pointer to the pull strength obtained.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
Example: Obtain the pull strength of a pin.
```
int32_t ret;
uint32_t strengthNum;
/* Obtain the pull strength of the pin. */
ret = PinGetStrength(handle, &strengthNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetStrength: failed, ret %d\n", ret);
return ret;
}
```
#### Setting the Pin Function
The pin function refers to the pin multiplexing function. The function of each pin is different. For details about the pin functions, see [pin_config.hcs](https://gitee.com/openharmony/device_soc_hisilicon/blob/master/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs).
Call **PinSetFunc** to set the pin function.
```
int32_t PinSetFunc(DevHandle handle, const char *funcName);
```
**Table 7** Description of PinSetFunc
<a name="table7"></a>
| Parameter | Description |
| ---------- | ------------------- |
| handle | Pin description handle. |
| funcName | Pointer to the pin function to set. |
| **Return Value**| **Description** |
| 0 | The operation is successful.|
| Negative value | The operation fails.|
Example: Set the pin function to LSADC_CH1 (ADC channel 1).
```
int32_t ret;
char funcName = "LSADC_CH1";
/* Sets the pin function. */
ret = PinSetFunc(handle, funcName);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinSetFunc: failed, ret %d\n", ret);
return ret;
}
```
#### Obtaining the Pin Function
Call **PinGetFunc** to obtain the pin function set.
```
int32_t PinGetFunc(DevHandle handle, const char **funcName);
```
**Table 8** Description of PinGetFunc
<a name="table8"></a>
| Parameter | Description |
| ---------- | --------------------- |
| handle | Pin description handle. |
| funcName | Pointer to the function name obtained.|
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative value | The operation fails. |
Example: Obtain the pin function.
```
int32_t ret;
char *funcName;
/* Obtain the pin function. */
ret = PinGetFunc(handle,&funcName);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetFunc: failed, ret %d\n", ret);
return ret;
}
```
#### Releasing a Pin Description Handle
After the operations on a pin are complete, call **PinPut** to release the pin description handle.
```
void PinPut(DevHandle handle);
```
**Table 9** Description of PinPut
<a name="table9"></a>
| Parameter | Description |
| ---------- | -------------- |
| handle | Pin description handle. |
| **Return Value**| **Description**|
| NA | No value is returned. |
Example: Release a pin description handle.
```
PinPut(handle);
```
## Development Example<a name="section10"></a>
The procedure is as follows:
1. Pass in the pin name to obtain the pin description handle.
2. Set the pull type of the pin. If the operation fails, release the pin description handle.
3. Obtain the pull type of the pin. If the operation fails, release the pin description handle.
4. Set the pull strength of the pin. If the operation fails, release the pin description handle.
5. Obtain the pin pull strength. If the operation fails, release the pin description handle.
5. Set the pin function. If the operation fails, release the pin description handle.
6. Obtain the pin function. If the operation fails, release the pin description handle.
7. Release the pin description handle if no operation needs to be performed on the pin.
```
#include "hdf_log.h" /* Header file for log APIs */
#include "pin_if.h" /* Header file for standard pin APIs */
int32_t PinTestSample(void)
{
int32_t ret;
uint32_t strengthNum;
enum PinPullType pullTypeNum;
char pinName;
char *funName;
DevHandle handle = NULL;
/* Pin name. Set it to the actual pin name. */
pinName = "P18";
/* Obtain the pin description handle. */
handle = PinGet(pinName);
if (handle == NULL) {
HDF_LOGE("PinGet: failed!\n");
return;
}
/* Set the pull type to pull-up for the pin. */
pullTypeNum = 1;
ret = PinSetPull(handle, pullTypeNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinSetPull: failed, ret %d\n", ret);
goto ERR;
}
/* Obtain the pull type of the pin. */
ret = PinGetPull(handle, &pullTypeNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetPull: failed, ret %d\n", ret);
goto ERR;
}
/* Set the pull strength of the pin to 2. */
strengthNum = 2;
ret = PinSetStrength(handle, strengthNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinSetStrength: failed, ret %d\n", ret);
goto ERR;
}
/* Obtain the pull strength of the pin. */
ret = PinGetStrength(handle, &strengthNum);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetStrength: failed, ret %d\n", ret);
goto ERR;
}
/* Set the pin function to LSADC_CH1. */
funName = "LSADC_CH1";
ret = PinSetFunc(handle, funName);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinSetFunc: failed, ret %d\n", ret);
goto ERR;
}
/* Obtain the pin function. */
ret = PinGetFunc(handle, &funcName);
if (ret != HDF_SUCCESS) {
HDF_LOGE("PinGetFunc: failed, ret %d\n", ret);
goto ERR;
}
ERR:
/* Release the pin description handle. */
PinPut(handle);
return ret;
}
# Pin<a name="title_PinDevelop"></a> # Pin
## Overview<a name="section1_PinDevelop"></a> ## Overview
The pin module controls the states and functionalities of system pins. In the Hardware Driver Foundation (HDF), the pin module uses the service-free mode for API adaptation. The service-free mode applies to 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. ### Pin
The pin, also called pin controller, manages pin resources of system on a chip (SoC) vendors and provides the pin multiplexing function.
Figure 1 Service-free mode ### Basic Concepts
![image1](figures/service-free-mode.png "service-free-mode")
## Available APIs<a name="section2_PinDevelop"></a> Pin, as a software concept, provides APIs for uniformly managing the pins from different SoC vendors, providing the pin multiplexing function, and configuring the electrical features of pins.
**PinCntlrMethod**: - SoC
An SOC is a chip that integrates microprocessors, analog IP cores, digital IP cores, and memory for specific purposes.
- Pin multiplexing
When the number of pins of a chip cannot handle the increasing connection requests, you can set the software registers to make the pins to work in different states.
### Working Principles
In the HDF, the pin module does not support the user mode and therefore does not need to publish services. It uses the service-free mode in interface adaptation. The service-free mode applies to the devices that do not provide user-mode APIs or the OS that does not distinguish the user mode and the kernel mode. The **DevHandle**, a void pointer, directly points to the kernel mode address of the device object.
The pin module is divided into the following layers:
- Interface layer: provides APIs for obtaining a pin, setting or obtaining the pull type, pull strength, and functions of a pin, and releasing a pin.
- Core layer: provides the capabilities of matching pin resources and adding, removing, and managing pin controllers. The core layer interacts with the adaptation layer by using hooks.
- Adaptation layer: instantiates hooks to implement specific functions.
**Figure 1** Service-free mode
![](figures/service-free-mode.png)
### Constraints
Currently, the pin module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
The pin module is used to manage pin resources. When the devices from SoC vendors interconnect with the HDF, the pin driver needs to be adapted.
### Available APIs
The **PinCntlrMethod** APIs are used to call the functions of the pin driver.
**PinCntlrMethod** definition:
```c ```c
struct PinCntlrMethod { struct PinCntlrMethod {
...@@ -25,290 +60,370 @@ struct PinCntlrMethod { ...@@ -25,290 +60,370 @@ struct PinCntlrMethod {
**Table 1** APIs for the members in the PinCntlrMethod structure **Table 1** APIs for the members in the PinCntlrMethod structure
| API | Input Parameter | Return Value| Description| | API | Input Parameter | Output Parameter | Return Value| Description|
| ------------ | ------------------------------------------- | ------ | ---- | | ------------ | ------------------------------------------- | ------ | ---- | ---- |
| SetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pull type of the pin. It is an enum constant.|HDF_STATUS|Sets the pull type of a pin.| | SetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pull type of the pin. It is an enum constant.| -|HDF_STATUS|Sets the pull type of a pin.|
| GetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**pullType**: pointer to the pull type of the pin.| HDF_STATUS| Obtains the pull type of a pin.| | GetPinPull | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **pullType**: pointer to the pull type of the pin.| HDF_STATUS| Obtains the pull type of a pin.|
| SetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pull strength of the pin. It is a uint32_t variable.| HDF_STATUS| Sets the pull strength of a pin.| | SetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pull strength of the pin. It is a uint32_t variable.| -| HDF_STATUS| Sets the pull strength of a pin.|
| GetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**strength**: pointer to the pull strength of the pin.| HDF_STATUS| Obtains the pull strength of a pin.| | GetPinStrength | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **strength**: pointer to the pull strength of the pin.| HDF_STATUS| Obtains the pull strength of a pin.|
| SetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char pointer to the pin functionality.| HDF_STATUS| Sets the pin functionality.| | SetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char pointer to the pin function.| -| HDF_STATUS| Sets the pin function.|
| GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.<br>**funcName**: char double pointer to the pin functionality.| HDF_STATUS| Obtains the pin functionalities.| | GetPinFunc | **cntlr**: structure pointer to the pin controller at the core layer.<br>**index**: pin index, which is a uint32_t variable.| **funcName**: char double pointer to the pin function.| HDF_STATUS| Obtains the pin function.|
### How to Develop
## How to Develop<a name="section3_PinDevelop"></a> The pin module adaptation procedure is as follows:
The pin module adaptation involves the following steps: - Instantiate the driver entry.
- Configure attribute files.
- Instantiate the core layer APIs.
- Debug the driver.
1. Instantiate the driver entry. 1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure. - Instantiate the **HdfDriverEntry** structure.
Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF. - Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release()** to release driver resources and exit.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file. ```c
- (Optional) Add the **pin_config.hcs** file. static struct HdfDriverEntry g_hi35xxPinDriverEntry = {
.moduleVersion = 1,
.Bind = Hi35xxPinBind,
.Init = Hi35xxPinInit,
.Release = Hi35xxPinRelease,
.moduleName = "hi35xx_pin_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
};
HDF_INIT(g_hi35xxPinDriverEntry);// Call HDF_INIT to register the driver entry with the HDF.
```
2. Configure attribute files.
- Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
```c
root {
device_info {
platform :: host {
hostName = "platform_host";
priority = 50;
device_pin :: device {
device0:: deviceNode { // Set an HDF device node for each pin controller.
policy = 0; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
priority = 10; // Driver startup priority.
permission = 0644; // Permission to create device nodes for the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "hi35xx_pin_driver";
/* (Mandatory) Set the controller private data, which must be same as that in pin_config.hcs. */
deviceMatchAttr = "hisilicon_hi35xx_pin_0";
}
device1 :: deviceNode {
policy = 0;
priority = 10;
permission = 0644;
moduleName = "hi35xx_pin_driver";
deviceMatchAttr = "hisilicon_hi35xx_pin_1";
}
......
}
}
}
}
```
- Add the **pin_config.hcs** file.
Configure the device attributes in the **device/soc/hisilicon/hi3516dv300/sdk_liteos/hdf_config/pin/pin_config.hcs** file. The parameters are set as follows:
```c
root {
platform {
pin_config_hi35xx {
template pin_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
number = 0; // (Mandatory) Controller ID.
regStartBasePhy = 0; // (Mandatory) Start physical base address of the register.
regSize = 0; // (Mandatory) Register bit width.
PinCount = 0; // (Mandatory) Number of pins.
match_attr = "";
template pin_desc {
pinName = ""; // (Mandatory) Name of the pin.
init = 0; // (Mandatory) Default value of the register.
F0 = ""; // (Mandatory) Function 0.
F1 = ""; // Function 1.
F2 = ""; // Function 2.
F3 = ""; // Function 3.
F4 = ""; // Function 4.
F5 = ""; // Function 5.
}
}
controller_0 :: pin_controller {
number = 0;
regStartBasePhy = 0x10FF0000;
regSize = 0x48;
pinCount = 18;
match_attr = "hisilicon_hi35xx_pin_0";
T1 :: pin_desc {
pinName = "T1";
init = 0x0600;
F0 = "EMMC_CLK";
F1 = "SFC_CLK";
F2 = "SFC_BOOT_MODE";
}
...... // Correspond to the pins of the pin controller. Add pins according to actual situation.
}
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
}
}
}
```
3. Instantiate the pin controller object. 3. Instantiate the pin controller object.
- Initialize the **PinCntlr** object. - Initialize the **PinCntlr** object.
Call **Hi35xxPinCntlrInit** to initialize the **PinCntlr** members.
- Instantiate **PinCntlrMethod** in the **PinCntlr** object.
```c
>![](../public_sys-resources/icon-note.gif) **NOTE** struct Hi35xxPinDesc {
// Pin name.
const char *pinName;
// Initial value.
uint32_t init;
// Index of the pin.
uint32_t index;
// Pull type of the pin.
int32_t pullType;
// Pull strength of the pin.
int32_t strength;
// Array of pin function names.
const char *func[HI35XX_PIN_FUNC_MAX];
};
>For details, see [Available APIs](#section2_PINDevelop). struct Hi35xxPinCntlr {
// Pin controller.
4. Debug the driver. struct PinCntlr cntlr;
// Pointer to the pin description structure.
- (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted. struct Hi35xxPinDesc *desc;
// Register mapping address.
volatile unsigned char *regBase;
// ID of the pin controller.
uint16_t number;
// Start address of the register physical base addresses.
uint32_t regStartBasePhy;
// Register bit width.
uint32_t regSize;
// Number of pins.
uint32_t pinCount;
};
// PinCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init() function.
struct PinCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct PinCntlrMethod *method;
struct DListHead node; // Node in the linked list.
OsalSpinlock spin; // Spinlock.
uint16_t number; // ID of the pin controller.
uint16_t pinCount; // Number of pins.
struct PinDesc *pins;
void *priv; // Private data.
};
// Initialize PinCntlr.
static int32_t Hi35xxPinCntlrInit(struct HdfDeviceObject *device, struct Hi35xxPinCntlr *hi35xx)
{
struct DeviceResourceIface *drsOps = NULL;
int32_t ret;
// Read the pin controller attributes from the .hcs file.
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
HDF_LOGE("%s: invalid drs ops fail!", __func__);
return HDF_FAILURE;
}
ret = drsOps->GetUint16(device->property, "number", &hi35xx->number, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read number failed", __func__);
return ret;
}
ret = drsOps->GetUint32(device->property, "regStartBasePhy", &hi35xx->regStartBasePhy, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read regStartBasePhy failed", __func__);
return ret;
}
ret = drsOps->GetUint32(device->property, "regSize", &hi35xx->regSize, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read regSize failed", __func__);
return ret;
}
ret = drsOps->GetUint32(device->property, "pinCount", &hi35xx->pinCount, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read pinCount failed", __func__);
return ret;
}
// Assign the values read to the members of the pin controller to initialize the pin controller.
hi35xx->cntlr.pinCount = hi35xx->pinCount;
hi35xx->cntlr.number = hi35xx->number;
hi35xx->regBase = OsalIoRemap(hi35xx->regStartBasePhy, hi35xx->regSize); // Pin controller mapping.
if (hi35xx->regBase == NULL) {
HDF_LOGE("%s: remap Pin base failed", __func__);
return HDF_ERR_IO;
}
hi35xx->desc = (struct Hi35xxPinDesc *)OsalMemCalloc(sizeof(struct Hi35xxPinDesc) * hi35xx->pinCount);
hi35xx->cntlr.pins = (struct PinDesc *)OsalMemCalloc(sizeof(struct PinDesc) * hi35xx->pinCount);
return HDF_SUCCESS;
}
```
## Development Example<a name="section4_PinDevelop"></a> - Instantiate the callback structure **PinCntlrMethod** in **PinCntlr**. Other members are initialized by using the **Init()** function.
The following uses **pin_hi35xx.c** as an example to present the content to be provided by the vendor to implement device functionalities. ```c
// The members of the PinCntlrMethod structure are all callbacks. Vendors need to implement the corresponding functions according to Table 1.
static struct PinCntlrMethod g_method = {
.SetPinPull = Hi35xxPinSetPull, // Set the pull type.
.GetPinPull = Hi35xxPinGetPull, // Obtains the pull type.
.SetPinStrength = Hi35xxPinSetStrength, // Set the pull strength.
.GetPinStrength = Hi35xxPinGetStrength, // Obtains the pull strength.
.SetPinFunc = Hi35xxPinSetFunc, // Set the pin functions.
.GetPinFunc = Hi35xxPinGetFunc, // Obtain the pin functions.
};
```
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf\_device\_desc.h**), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke. - **Init()** function
Generally, the HDF calls the **Bind** function and then the **Init** function to load the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Pin driver entry reference: Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
| **State** | **Description** |
| ---------------------- | -------------- |
| HDF_ERR_INVALID_OBJECT | Invalid controller object.|
| HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
| HDF_ERR_INVALID_PARAM | Invalid parameter. |
| HDF_ERR_IO | I/O error. |
| HDF_SUCCESS | Initialization successful. |
| HDF_FAILURE | Initialization failed. |
Function description:
Initializes the custom structure object and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd()** function.
```c
static int32_t Hi35xxPinReadFunc(struct Hi35xxPinDesc *desc, const struct DeviceResourceNode *node, struct DeviceResourceIface *drsOps)
{
int32_t ret;
uint32_t funcNum = 0;
// Read the pin function names of the pin controller child nodes from the .hcs file.
ret = drsOps->GetString(node, "F0", &desc->func[funcNum], "NULL");
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read F0 failed", __func__);
return ret;
}
```c funcNum++;
static struct HdfDriverEntry g_hi35xxPinDriverEntry = { ret = drsOps->GetString(node, "F1", &desc->func[funcNum], "NULL");
.moduleVersion = 1, if (ret != HDF_SUCCESS) {
.Bind = Hi35xxPinBind, HDF_LOGE("%s: read F1 failed", __func__);
.Init = Hi35xxPinInit, return ret;
.Release = Hi35xxPinRelease, }
.moduleName = "hi35xx_pin_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.
HDF_INIT(g_hi35xxPinDriverEntry);
```
2. Add **deviceNode** to the **device\_info.hcs** file, and set the device attributes in the **pin\_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 **PinCntlr** members at the core layer. funcNum++;
......
>![](../public_sys-resources/icon-note.gif) **NOTE** return HDF_SUCCESS;
>If there are multiple devices, add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **pin\_config** file. }
- **device\_info.hcs** reference: static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node, struct Hi35xxPinCntlr *hi35xx, int32_t index)
{
```c int32_t ret;
root { struct DeviceResourceIface *drsOps = NULL;
device_info { // Read the pin attributes of the pin controller child nodes from the .hcs file.
platform :: host { drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
hostName = "platform_host"; if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
priority = 50; HDF_LOGE("%s: invalid drs ops fail!", __func__);
device_pin :: device { return HDF_FAILURE;
device0:: deviceNode { // Set an HDF device node for each pin controller. }
policy = 0; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required. ret = drsOps->GetString(node, "pinName", &hi35xx->desc[index].pinName, "NULL");
priority = 10; // Driver startup priority. if (ret != HDF_SUCCESS) {
permission = 0644; // Permission to create device nodes for the driver. HDF_LOGE("%s: read pinName failed", __func__);
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */ return ret;
moduleName = "hi35xx_Pin_driver"; }
/* (Mandatory) Set the controller private data, which must be same as that in Pin_config.hcs. */ ......
deviceMatchAttr = "hisilicon_hi35xx_Pin_0"; ret = Hi35xxPinReadFunc(&hi35xx->desc[index], node, drsOps);
} if (ret != HDF_SUCCESS) {
device1 :: deviceNode { HDF_LOGE("%s:Pin read Func failed", __func__);
policy = 0; return ret;
priority = 10; }
permission = 0644; hi35xx->cntlr.pins[index].pinName = hi35xx->desc[index].pinName;
moduleName = "hi35xx_Pin_driver"; hi35xx->cntlr.pins[index].priv = (void *)node;
deviceMatchAttr = "hisilicon_hi35xx_Pin_1"; ......
} return HDF_SUCCESS;
... }
}
}
}
}
```
- **Pin\_config.hcs** reference:
```c
root {
platform {
Pin_config_hi35xx {
template Pin_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
number = 0; // (Mandatory) Controller ID.
regStartBasePhy = 0; // (Mandatory) Start physical base address of the register.
regSize = 0; // (Mandatory) Register bit width.
PinCount = 0; // (Mandatory) Number of pins.
match_attr = "";
template Pin_desc {
PinName = ""; // (Mandatory) Pin name.
init = 0; // (Mandatory) Default value of the register.
F0 = ""; // (Mandatory) Functionality 0.
F1 = ""; // Functionality 1.
F2 = ""; // Functionality 2.
F3 = ""; // Functionality 3.
F4 = ""; // Functionality 4.
F5 = ""; // Functionality 5.
}
}
controller_0 :: Pin_controller {
number = 0;
regStartBasePhy = 0x10FF0000;
regSize = 0x48;
PinCount = 18;
match_attr = "hisilicon_hi35xx_Pin_0";
T1 :: Pin_desc {
PinName = "T1";
init = 0x0600;
F0 = "EMMC_CLK";
F1 = "SFC_CLK";
F2 = "SFC_BOOT_MODE";
}
...
}
...// Each pin controller corresponds to a controller node. If there are multiple pin controllers, add the corresponding controller nodes one by one.
}
}
}
```
3. Initialize the **PinCntlr** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **PinCntlrMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**).
- Initializing the vendor custom structure
The **PinCntlr** structure holds parameters and data for the driver. The HDF obtains the values in **pin\_config.hcs** using **DeviceResourceIface**.
```c
// PinCntlr is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct PinCntlr {
struct IDeviceIoService service;
struct HdfDeviceObject *device;
struct PinCntlrMethod *method;
struct DListHead node;
OsalSPinlock sPin;
uint16_t number;
uint16_t PinCount;
struct PinDesc *Pins;
void *priv;
};
struct PinDesc {
const char *PinName; // Pointer to the pin name.
void *priv;
};
```
- Instantiating **PinCntlrMethod** (other members are initialized by **Init**)
```c
// Example of Pin_hi35xx.c: Instantiate the hook.
static struct PinCntlrMethod g_method = {
.SetPinPull = Hi35xxPinSetPull,
.GetPinPull = Hi35xxPinGetPull,
.SetPinStrength = Hi35xxPinSetStrength,
.GetPinStrength = Hi35xxPinGetStrength,
.SetPinFunc = Hi35xxPinSetFunc,
.GetPinFunc = Hi35xxPinGetFunc,
};
```
- **Init** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
**Table 2** HDF\_STATUS
<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>State</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 and **PinCntlr** members, and connects to the pin controller by calling the **PinCntlrAdd** function at the core layer.
```c
static int32_t Hi35xxPinInit(struct HdfDeviceObject *device) static int32_t Hi35xxPinInit(struct HdfDeviceObject *device)
{ {
... ......
struct Hi35xxPinCntlr *hi35xx = NULL; struct Hi35xxPinCntlr *hi35xx = NULL;
... ......
ret = Hi35xxPinCntlrInit(device, hi35xx); // Obtain .hcs information. ret = Hi35xxPinCntlrInit(device, hi35xx); // Initialize the pin controller.
... ......
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { // Traverses each child node of the pin controller.
ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); // (Mandatory) The implementation is as follows: ret = Hi35xxPinParsePinNode(childNode, hi35xx, index); // Parsing the child nodes.
... ......
} }
hi35xx->cntlr.method = &g_method; // Instantiate OPS. hi35xx->cntlr.method = &g_method; // Instantiate method.
ret = PinCntlrAdd(&hi35xx->cntlr); // Connect to the controller. ret = PinCntlrAdd(&hi35xx->cntlr); // Connect to the controller.
... if (ret != HDF_SUCCESS) {
} HDF_LOGE("%s: add Pin cntlr: failed", __func__);
ret = HDF_FAILURE;
static int32_t Hi35xxPinParsePinNode(const struct DeviceResourceNode *node, }
struct Hi35xxPinCntlr *hi35xx, return HDF_SUCCESS;
int32_t index)
{
...
hi35xx->cntlr.Pins[index].PinName = hi35xx->desc[index].PinName; // Instantiate PinName.
hi35xx->cntlr.Pins[index].priv = (void *)node; // Instantiate nodes.
...
} }
```
- **Release()** function
- **Release** function
Input parameters: Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration. **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs information.
Return value: Return value:
Function description: Function description:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources. Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources.
```c ```c
static void Hi35xxPinRelease(struct HdfDeviceObject *device) static void Hi35xxPinRelease(struct HdfDeviceObject *device)
{ {
struct PinCntlr *cntlr = NULL; int32_t ret;
... uint16_t number;
PinCntlrRemove(cntlr);// (Mandatory) Call the function at the core layer to release pin controller devices and services. struct PinCntlr *cntlr = NULL;
... struct Hi35xxPinCntlr *hi35xx = NULL;
struct DeviceResourceIface *drsOps = NULL;
if (device == NULL || device->property == NULL) {
HDF_LOGE("%s: device or property is null", __func__);
return;
}
// Read the pin controller ID from the .hcs file.
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetString == NULL) {
HDF_LOGE("%s: invalid drs ops", __func__);
return;
}
ret = drsOps->GetUint16(device->property, "number", &number, 0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read cntlr number failed", __func__);
return;
}
cntlr = PinCntlrGetByNumber(number); // Obtain the pin controller based on the controller ID.
PinCntlrRemove(cntlr);
hi35xx = (struct Hi35xxPinCntlr *)cntlr;
if (hi35xx != NULL) {
if (hi35xx->regBase != NULL) {
OsalIoUnmap((void *)hi35xx->regBase);
}
OsalMemFree(hi35xx);
}
} }
``` ```
4. Debug the driver.
(Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
# PWM<a name="title_PWM_des"></a> # PWM
## Overview <a name="section1_PWM_des"></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. ## Overview
Pulse width modulation (PWM) is a technology that digitally encodes analog signal levels and converts them into pulses. It can be used for motor control and backlight brightness adjustment.
The PWM APIs provide a set of functions for operating a PWM device, including those for:
- Opening or closing a PWM device handle
The PWM APIs provide a set of functions for operating a PWM device, including those for:
- Obtaining and releasing a PWM device handle
- Setting the PWM period, signal ON-state time, and polarity - Setting the PWM period, signal ON-state time, and polarity
- Enabling and disabling a PWM device - Enabling and disabling a PWM device
- Obtaining and setting PWM parameters - Obtaining and setting PWM parameters
### PwmConfig Structure<a name="section1.1_PWM_des"></a>
**Table 1** PwmConfig structure
<a name="table1_PWM_des"></a>
| Parameter| Description|
| -------- | ------------------------------------------------------------ |
| duty | Time that a signal is in the ON state, in ns.|
| period | Time for a signal to complete an on-and-off cycle, in ns.|
| number | Number of square waves to generate. A positive value indicates the number of square waves to generate. The value <b>0</b> means to generate square waves repeatedly.|
| polarity | PWM signal polarity, which can be **PWM\_NORMAL\_POLARITY** or **PWM\_INVERTED\_POLARITY**.|
| status | PWM device status, which can be enabled or disabled.|
## Available APIs<a name="section2_PWM_des"></a>
**Table 2** PWM device APIs
<a name="table2_PWM_des"></a>
<table border="0" cellpadding="0" cellspacing="0" width="800" style="border-collapse:
collapse;table-layout:fixed;width:700pt">
<colgroup><col class="xl65" width="300" style="mso-width-source:userset;mso-width-alt:13728;
width:300pt">
<col width="250" style="mso-width-source:userset;mso-width-alt:13216;width:250pt">
<col width="300" style="mso-width-source:userset;mso-width-alt:28352;width:300pt">
</colgroup><tbody><tr height="19" style="height:14.25pt">
<td height="19" class="xl66" width="300" style="height:14.25pt;width:300pt">Category</td>
<td class="xl67" width="250" style="width:250pt">API</td>
<td class="xl67" width="300" style="width:300pt">Description</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Operating PWM handles</td>
<td>PwmOpen</td>
<td>Opens the handle of a PWM device.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmClose</td>
<td>Closes the handle of a PWM device.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Enabling or disabling PWM</td>
<td>PwmEnable</td>
<td>Enables a PWM device.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmDisable</td>
<td>Disables a PWM device.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="3" height="57" class="xl65" style="height:42.75pt">Performing PWM configuration</td>
<td>PwmSetPeriod</td>
<td>Sets the PWM period.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmSetDuty</td>
<td>Sets the signal ON-state time.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmSetPolarity</td>
<td>Sets the PWM signal polarity.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Setting or obtaining the PWM configuration</td>
<td>PwmSetConfig</td>
<td>Sets PWM device parameters.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">PwmGetConfig</td>
<td>Obtains PWM device parameters.</td>
</tr>
<!--[if supportMisalignedColumns]-->
<tr height="0" style="display:none">
<td width="429" style="width:322pt"></td>
<td width="413" style="width:310pt"></td>
<td width="886" style="width:665pt"></td>
</tr>
<!--[endif]-->
</tbody></table>
>![](W:\doc\docs\en\device-dev\public_sys-resources\icon-note.gif) **NOTE:**
>The PWM module can be used in kernel mode but not in user mode.
## Usage Guidelines<a name="section3_PWM_des"></a>
### How to Use<a name="section3.1_PWM_des"></a>
During the OS startup process, the driver management module loads the PWM driver based on the configuration file. Then, the PWM driver detects the PWM device and initializes the driver.
[Figure 1](#fig1_PWM_des) shows the general process of using the PWM module.
**Figure 1** Process of using the PWM module<a name="fig1_PWM_des"></a>
### PwmConfig Structure
**Table 1** PwmConfig structure
| Parameter| Description|
| -------- | -------- |
| duty | Time that a signal is in the ON state, in ns.|
| period | Time for a signal to complete an on-and-off cycle, in ns.|
| number | Number of square waves to generate.<br>-&nbsp;Positive value: indicates the number of square waves to generate.<br>-&nbsp;**0**: indicates that square waves are generated continuously.|
| polarity | PWM signal polarity, which can be positive or reverse.|
| status | PWM device status, which can be enabled or disabled.|
## Available APIs
**Table 2** PWM driver APIs
| Category| Description|
| -------- | -------- |
| Operating PWM handles| -&nbsp;**PwmOpen**: opens the device handle of a PWM device.<br>-&nbsp;**PwmClose**: closes the device handle of a PWM device.|
| Enabling or disabling PWM| -&nbsp;**PwmEnable**: enables a PWM device.<br>-&nbsp;**PwmDisable**: disables a PWM device.|
| Setting PWM| -&nbsp;**PwmSetPeriod**: sets the PWM period.<br>-&nbsp;**PwmSetDuty**: sets the signal ON-state time.<br>-&nbsp;**PwmSetPolarity**: sets the PWM signal polarity.|
| Setting or obtaining PWM configuration| -&nbsp;**PwmSetConfig**: sets PWM device parameters.<br>-&nbsp;**PwmGetConfig**: obtains PWM device parameters.|
> ![icon-note.gif](../public_sys-resources/icon-note.gif) **NOTE**<br/>
> All APIs described in this document can be called only in the kernel space.
## Usage Guidelines
### How to Use
The figure below shows the general process of using the PWM.
**Figure 1** Process of using the PWM module
![](figures/process-of-using-PWM.png) ![](figures/process-of-using-PWM.png)
### Opening a PWM Device Handle<a name="section3.2_PWM_des"></a>
### Opening a PWM Device Handle
Before performing operations on a PWM device, call **PwmOpen** to open the device handle. Before performing operations on a PWM device, call **PwmOpen** to open the device handle.
```c
```
DevHandle PwmOpen(uint32_t num); DevHandle PwmOpen(uint32_t num);
``` ```
**Table 3** PwmOpen **Table 3** Description of PwmOpen
<a name="table3_PWM_des"></a>
| Parameter| Description| | **Parameter**| **Description**|
| ---------- | ----------------------- | | -------- | -------- |
| num | PWM device number.| | num | PWM device number. |
| **Return Value** | **Description**| | **Return Value** | **Description** |
| handle | Handle of the PWM device obtained.| | handle | Handle of the PWM device obtained.|
| NULL | The operation fails.| | NULL | The operation fails. |
Example: Open the device handle of PWM device 0.
```c ```
uint32_t num = 0; /* PWM device number. */ uint32_t num = 0; /* PWM device number. */
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -139,48 +87,49 @@ if (handle == NULL) { ...@@ -139,48 +87,49 @@ if (handle == NULL) {
} }
``` ```
### Closing a PWM Device Handle<a name="section3.3_PWM_des"></a>
Close a PWM device to release resources. ### Closing a PWM Device Handle
```c Call **PwmClose()** to close a PWM device handle to release resources.
void PwmClose(DevHandle handle);
```
**Table 4** PwmClose
<a name="table4_PWM_des"></a> ```
voidPwmClose(DevHandle handle);
```
| Parameter| Description| **Table 4** Description of PwmClose
| ------ | ----------- |
| handle | PWM device handle to close.|
| **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle to close. |
```c
```
/* Close a PWM device handle. */ /* Close a PWM device handle. */
PwmClose(handle); PwmClose(handle);
``` ```
### Enabling a PWM Device<a name="section3.4_PWM_des"></a>
Enable a PWM device. ### Enabling a PWM Device
```c Call **PwmEnable()** to enable a PWM device.
```
int32_t PwmEnable(DevHandle handle); int32_t PwmEnable(DevHandle handle);
``` ```
**Table 5** PwmEnable **Table 5** Description of PwmEnable
<a name="table5_PWM_des"></a> | **Parameter**| **Description**|
| -------- | -------- |
| Parameter| Description| | handle | PWM device handle. |
| ---------- | -------------- |
| handle | PWM device handle.|
| **Return Value** | **Description** | | **Return Value** | **Description** |
| 0 | The operation is successful.| | 0 | The operation is successful. |
| Negative number| The operation fails.| | Negative number | The operation fails. |
```c ```
int32_t ret; int32_t ret;
/* Enable a PWM device. */ /* Enable a PWM device. */
...@@ -190,26 +139,27 @@ if (ret != 0) { ...@@ -190,26 +139,27 @@ if (ret != 0) {
} }
``` ```
### Disabling a PWM Device<a name="section3.5_PWM_des"></a>
Disable a PWM device. ### Disabling a PWM Device
Call **PwmDisable()** to disable a PWM device.
```c
```
int32_t PwmDisable(DevHandle handle); int32_t PwmDisable(DevHandle handle);
``` ```
**Table 6** PwmDisable **Table 6** Description of PwmDisable
<a name="table6_PWM_des"></a> | **Parameter**| **Description**|
| -------- | -------- |
| Parameter| Description| | handle | PWM device handle. |
| ---------- | -------------- |
| handle | PWM device handle.|
| **Return Value** | **Description** | | **Return Value** | **Description** |
| 0 | The operation is successful.| | 0 | The operation is successful. |
| Negative number| The operation fails.| | Negative number | The operation fails. |
```c ```
int32_t ret; int32_t ret;
/* Disable a PWM device. */ /* Disable a PWM device. */
...@@ -219,27 +169,28 @@ if (ret != 0) { ...@@ -219,27 +169,28 @@ if (ret != 0) {
} }
``` ```
### Setting the PWM Period<a name="section3.6_PWM_des"></a>
Set the PWM period. ### Setting the PWM Period
Call **PwmSetPeriod()** to set the PWM period.
```c ```
int32_t PwmSetPeriod(DevHandle handle, uint32_t period); int32_t PwmSetPeriod(DevHandle handle, uint32_t period);
``` ```
**Table 7** PwmSetPeriod **Table 7** Description of PwmSetPeriod
<a name="table7_PWM_des"></a>
| Parameter| Description| | **Parameter**| **Description**|
| ---------- | ------------------------ | | -------- | -------- |
| handle | PWM device handle.| | handle | PWM device handle. |
| period | PWM period to set, in ns.| | period | PWM period to set, in ns.|
| **Return Value**| **Description**| | **Return Value**| **Description** |
| 0 | The operation is successful.| | 0 | The operation is successful. |
| Negative number| The operation fails.| | Negative number | The operation fails. |
```c
```
int32_t ret; int32_t ret;
/* Set the PWM period to 50000000 ns.*/ /* Set the PWM period to 50000000 ns.*/
...@@ -248,27 +199,29 @@ if (ret != 0) { ...@@ -248,27 +199,29 @@ if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
### Setting the PWM Signal ON-State Time<a name="section3.7_PWM_des"></a>
Set the time that the PWM signal is in the ON state.
```c ### Setting the PWM Signal ON-State Time
Call **PwmSetDuty()** to set the time that the PWM signal is in the ON state.
```
int32_t PwmSetDuty(DevHandle handle, uint32_t duty); int32_t PwmSetDuty(DevHandle handle, uint32_t duty);
``` ```
**Table 8** PwmSetDuty **Table 8** Description of PwmSetDuty
<a name="table8_PWM_des"></a>
| Parameter| Description| | **Parameter**| **Description**|
| ---------- | ---------------------------- | | -------- | -------- |
| handle | PWM device handle.| | handle | PWM device handle. |
| duty | Time that the signal is in the ON state, in ns.| | duty | Time that the signal is in the ON state, in ns.|
| **Return Value**| **Description**| | **Return Value**| **Description** |
| 0 | The operation is successful.| | 0 | The operation is successful. |
| Negative number| The operation fails.| | Negative number | The operation fails. |
```c
```
int32_t ret; int32_t ret;
/* Set the signal ON-state time to 25000000 ns. */ /* Set the signal ON-state time to 25000000 ns. */
...@@ -277,27 +230,29 @@ if (ret != 0) { ...@@ -277,27 +230,29 @@ if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
### Setting the PWM Polarity<a name="section3.8_PWM_des"></a>
Set the signal polarity for a PWM device.
```c ### Setting the PWM Signal Polarity
Call **PwmSetPolarity()** to set the signal polarity for a PWM device.
```
int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity); int32_t PwmSetPolarity(DevHandle handle, uint8_t polarity);
``` ```
**Table 9** PwmSetPolarity **Table 9** Description of PwmSetPolarity
<a name="table9_PWM_des"></a>
| Parameter| Description| | **Parameter**| **Description**|
| ---------- | ------------------- | | -------- | -------- |
| handle | PWM device handle.| | handle | PWM device handle. |
| polarity | Polarity to set, which can be **PWM\_NORMAL\_POLARITY** or **PWM\_INVERTED\_POLARITY**.| | polarity | Polarity to set, which can be **PWM\_NORMAL\_POLARITY** or **PWM\_INVERTED\_POLARITY**.|
| **Return Value**| **Description**| | **Return Value**| **Description** |
| 0 | The operation is successful.| | 0 | The operation is successful. |
| Negative number| The operation fails.| | Negative number | The operation fails. |
```c
```
int32_t ret; int32_t ret;
/* Set the PWM polarity to PWM_INVERTED_POLARITY. */ /* Set the PWM polarity to PWM_INVERTED_POLARITY. */
...@@ -308,34 +263,34 @@ if (ret != 0) { ...@@ -308,34 +263,34 @@ if (ret != 0) {
``` ```
### Setting PWM Device Parameters<a name="section3.9_PWM_des"></a> ### Setting PWM Device Parameters
Set PWM device parameters. Call **PwmSetConfig()** to set PWM device parameters.
```c
```
int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config); int32_t PwmSetConfig(DevHandle handle, struct PwmConfig *config);
``` ```
**Table 10** PwmSetConfig **Table 10** Description of PwmSetConfig
<a name="table10_PWM_des"></a> | **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle to close. |
| \*config | Pointer to PWM parameters. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
| Parameter| Description|
| ---------- | -------------- |
| handle | PWM device handle.|
| *config | Pointer to PWM parameters.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative number| The operation fails.|
```c ```
int32_t ret; int32_t ret;
struct PwmConfig pcfg; struct PwmConfig pcfg;
pcfg.duty = 25000000; /* Set the signal ON-state time to 25000000 ns. */ pcfg.duty = 25000000; /* Set the signal ON-state time to 25000000 ns. */
pcfg.period = 50000000; /* Set the PWM period to 50000000 ns. */ pcfg.period = 50000000; /* Set the PWM period to 50000000 ns. */
pcfg.number = 0; /* Generate square waves repeatedly. */ pcfg.number = 0; /* Generate square waves repeatedly. */
pcfg.polarity = PWM_INVERTED_POLARITY; /* Set the PWM polarity to PWM_INVERTED_POLARITY. */ pcfg.polarity = PWM_INVERTED_POLARITY; /* Set the PWM polarity to PWM_INVERTED_POLARITY. */
pcfg.status = PWM_ENABLE_STATUS; /* Set the running status to Enabled. */ pcfg.status = PWM_ENABLE_STATUS; /* Set the running status to Enabled. */
/* Set PWM device parameters. */ /* Set PWM device parameters. */
ret = PwmSetConfig(handle, &pcfg); ret = PwmSetConfig(handle, &pcfg);
...@@ -344,27 +299,28 @@ if (ret != 0) { ...@@ -344,27 +299,28 @@ if (ret != 0) {
} }
``` ```
### Obtaining PWM Device Parameters<a name="section3.10_PWM_des"></a>
Obtain PWM device parameters. ### Obtaining PWM Device Parameters
Call **PwmGetConfig()** to obtain PWM device parameters.
```c
```
int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config); int32_t PwmGetConfig(DevHandle handle, struct PwmConfig *config);
``` ```
**Table 11** PwmGetConfig **Table 11** Description of PwmGetConfig
<a name="table11_PWM_des"></a> | **Parameter**| **Description**|
| -------- | -------- |
| handle | PWM device handle to close. |
| \*config | Pointer to PWM parameters. |
| **Return Value**| **Description** |
| 0 | The operation is successful. |
| Negative number | The operation fails. |
| Parameter| Description|
| ---------- | -------------- |
| handle | PWM device handle.|
| *config | Pointer to PWM parameters.|
| **Return Value**| **Description**|
| 0 | The operation is successful.|
| Negative number| The operation fails.|
```c ```
int32_t ret; int32_t ret;
struct PwmConfig pcfg; struct PwmConfig pcfg;
...@@ -375,10 +331,12 @@ if (ret != 0) { ...@@ -375,10 +331,12 @@ if (ret != 0) {
} }
``` ```
## Usage Example<a name="section4_PWM_des"></a>
## Development Example
The following example shows how to use the APIs to implement a PWM driver and manage the PWM device. The following example shows how to use the APIs to implement a PWM driver and manage the PWM device.
``` ```
void PwmTestSample(void) void PwmTestSample(void)
{ {
...@@ -387,12 +345,12 @@ void PwmTestSample(void) ...@@ -387,12 +345,12 @@ void PwmTestSample(void)
DevHandle handle = NULL; DevHandle handle = NULL;
struct PwmConfig pcfg; struct PwmConfig pcfg;
pcfg.duty = 20000000; /* Set the signal ON-state time to 20000000 ns. */ pcfg.duty = 20000000; /* Set the signal ON-state time to 20000000 ns. */
pcfg.period = 40000000; /* Set the PWM period to 40000000 ns. */ pcfg.period = 40000000; /* Set the PWM period to 40000000 ns. */
pcfg.number = 100; /* Generate 100 square waves. */ pcfg.number = 100; /* Generate 100 square waves. */
pcfg.polarity = PWM_NORMAL_POLARITY; /* Set the polarity to PWM_NORMAL_POLARITY. */ pcfg.polarity = PWM_NORMAL_POLARITY; /* Set the polarity to PWM_NORMAL_POLARITY. */
pcfg.status = PWM_ENABLE_STATUS; /* Set the running status to Enabled. */ pcfg.status = PWM_ENABLE_STATUS; /* Set the running status to Enabled. */
/* Enter the PWM device number. */ /* Enter the PWM device number. */
num = 1; num = 1;
...@@ -423,14 +381,14 @@ void PwmTestSample(void) ...@@ -423,14 +381,14 @@ void PwmTestSample(void)
HDF_LOGE("PwmSetPolarity: failed, ret %d\n", ret); HDF_LOGE("PwmSetPolarity: failed, ret %d\n", ret);
goto _ERR; goto _ERR;
} }
/* Obtain PWM device parameters. */ /* Obtain PWM device parameters. */
ret = PwmGetConfig(handle, &pcfg); ret = PwmGetConfig(handle, &pcfg);
if (ret != 0) { if (ret != 0) {
HDF_LOGE("PwmGetConfig: failed, ret %d\n", ret); HDF_LOGE("PwmGetConfig: failed, ret %d\n", ret);
goto _ERR; goto _ERR;
} }
/* Enable the PWM device. */ /* Enable the PWM device. */
ret = PwmEnable(handle); ret = PwmEnable(handle);
if (ret != 0) { if (ret != 0) {
...@@ -451,7 +409,7 @@ void PwmTestSample(void) ...@@ -451,7 +409,7 @@ void PwmTestSample(void)
HDF_LOGE("PwmDisable: failed, ret %d\n", ret); HDF_LOGE("PwmDisable: failed, ret %d\n", ret);
goto _ERR; goto _ERR;
} }
_ERR: _ERR:
/* Close the PWM device handle. */ /* Close the PWM device handle. */
PwmClose(handle); PwmClose(handle);
......
# Regulator<a name="title_REGULATOR_des"></a> # Regulator
## Overview<a name="section1_REGULATOR_des"></a>
## Overview
### Regulator
The regulator module controls the voltage and current supplies of some devices in the system. In an embedded system (especially a mobile phone), it is important to control the power consumption, which directly affects the battery endurance. You can use a regulator to shut down the power supply to an idle module in the system or reduce the voltage and current for the module. The regulator module controls the voltage and current supplies of some devices in the system. In an embedded system (especially a mobile phone), it is important to control the power consumption, which directly affects the battery endurance. You can use a regulator to shut down the power supply to an idle module in the system or reduce the voltage and current for the module.
The regulator APIs provide a set of methods for managing a regulator, including those for:
- The regulator APIs provide a set of functions for managing a regulator, including those for: - Opening or closing a regulator device handle
- Opening or closing a regulator device handle - Setting the output voltage and current for a regulator
- Setting the output voltage and current for a regulator - Enabling or disabling a regulator
- Enabling or disabling a regulator - Obtaining the voltage, current, and status of a regulator
- Obtaining the voltage, current, and status of a regulator
## Available APIs<a name="section2_REGULATOR_des"></a>
**Table 1** Regulator APIs
<a name="table1_REGULATOR_des"></a>
<table border="0" cellpadding="0" cellspacing="0" width="600" style="border-collapse:
collapse;table-layout:fixed;width:855pt">
<colgroup><col width="183" style="mso-width-source:userset;mso-width-alt:5856;width:137pt">
<col width="159" style="mso-width-source:userset;mso-width-alt:5088;width:119pt">
<col width="213" style="mso-width-source:userset;mso-width-alt:6816;width:160pt">
</colgroup><tbody><tr height="19" style="height:14.25pt">
<td height="19" width="183" style="height:14.25pt;width:137pt">Category</td>
<td width="159" style="width:119pt">API</td>
<td width="213" style="width:160pt">Description</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Operating a regulator device handle</td>
<td>RegulatorOpen</td>
<td>Opens a regulator device handle.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorClose</td>
<td>Closes a regulator device handle.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="3" height="57" class="xl65" style="height:42.75pt">Enabling or disable a regulator</td>
<td>RegulatorEnable</td>
<td>Enables a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorDisable</td>
<td>Disables a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorForceDisable</td>
<td>Forcibly disables a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Setting or obtaining the output voltage</td>
<td>RegulatorSetVoltage</td>
<td>Sets the output voltage for a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorGetVoltage</td>
<td>Obtains the output voltage of a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td rowspan="2" height="38" class="xl65" style="height:28.5pt">Setting or obtaining the output current</td>
<td>RegulatorSetCurrent</td>
<td>Sets the output current for a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" style="height:14.25pt">RegulatorGetCurrent</td>
<td>Obtains the output current of a regulator.</td>
</tr>
<tr height="19" style="height:14.25pt">
<td height="19" class="xl66" style="height:14.25pt">Querying the regulator status</td>
<td>RegulatorGetStatus</td>
<td>Obtains the regulator status.</td>
</tr>
<!--[if supportMisalignedColumns]-->
<tr height="0" style="display:none">
<td width="183" style="width:137pt"></td>
<td width="159" style="width:119pt"></td>
<td width="213" style="width:160pt"></td>
</tr>
<!--[endif]-->
</tbody></table>
>![](../public_sys-resources/icon-note.gif) **NOTE**
>The regulator module can be used in kernel mode but not in user mode.
## Usage Guidelines<a name="section3_REGULATOR_des"></a>
### How to Use<a name="section3.1_REGULATOR_des"></a>
During the OS startup process, the driver management module loads the regulator driver based on the configuration file. Then, the regulator driver detects the regulator devices and initializes the driver.
The figure below shows the process of using a regulator. ### Basic Concepts
- Calibrator
Software used to maintain stable output voltage when the output load is different from the input voltage.
- Consumer
The devices served by the regulator are called consumers. Consumers are classified into the following:
* Static consumer: Only the power needs to be turned on or off for this type of consumers. The voltage and current do not need to be changed. Generally, the consumers are set in the bootloader, firmware, and kernel board phases.
* Dynamic consumer: The voltage and current need to be changed based on operation requirements for this type of consumers.
- Power Management IC (PMIC)
Power management chipset provides efficient, reliable, and safe voltage regulation.
### Working Principles
In the Hardware Driver Foundation (HDF), the regulator module uses the unified service mode for API adaptation. In this mode, a device service is used as the regulator 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 regulator has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and more memory resources will be consumed by services.
The regulator module is divided into the following layers:
- The interface layer provides APIs for opening or closing a device and writing data.
- The core layer provides the capabilities of binding, initializing, and releasing devices.
- The adaptation layer implements other functions.
![](../public_sys-resources/icon-note.gif)NOTE<br/>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer.
**Figure 1** Unified service mode
![image1](figures/unified-service-mode.png)
### Constraints
**Figure 1** Process of using a regulator<a name="fig1_regulator_des"></a> Currently, the regulator module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
Regulators are used to:
- Control the voltage/current supplies of some devices in the system.
- Manage regulated power supplies.
### Available APIs
**Table 1** Regulator module APIs
| API | Description |
| --------------------- | ------------------------- |
| RegulatorOpen | Opens the regulator device handle.|
| RegulatorClose | Closes the regulator device handle.|
| RegulatorEnable | Enables a regulator. |
| RegulatorDisable | Disables a regulator. |
| RegulatorForceDisable | Forcibly disables a regulator. |
| RegulatorSetVoltage | Sets the regulator output voltage. |
| RegulatorGetVoltage | Obtains the regulator output voltage. |
| RegulatorSetCurrent | Sets the regulator output current. |
| RegulatorGetCurrent | Obtains the regulator output current. |
| RegulatorGetStatus | Obtains the regulator status. |
### How to Develop
During the OS startup process, the driver management module loads the regulator driver based on the configuration file. Then, the regulator driver detects the regulator devices and initializes the driver.
The figure below illustrates the process of using a regulator.
**Figure 2** Process of using a regulator
![](figures/process-of-using-regulator.png) ![](figures/process-of-using-regulator.png)
### Opening a Regulator Device Handle<a name="section3.2_REGULATOR_des"></a> #### Opening a Regulator Device Handle
Before operating a regulator, call **RegulatorOpen** to open the device handle of the regulator. This function returns the device handle of the regulator. Before operating a regulator, call **RegulatorOpen** to open the device handle of the regulator. This function returns the device handle of the regulator.
```c ```
DevHandle RegulatorOpen(const char *name); DevHandle RegulatorOpen(const char *name);
``` ```
**Table 2** Description of RegulatorOpen **Table 2** Description of RegulatorOpen
<a name="table2_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------------------- | | ---------- | ----------------------------- |
| name | Name of the target regulator. | | name | Name of the target regulator. |
...@@ -116,8 +108,9 @@ DevHandle RegulatorOpen(const char *name); ...@@ -116,8 +108,9 @@ DevHandle RegulatorOpen(const char *name);
| NULL | The operation fails. | | NULL | The operation fails. |
```c
/* Regulator name. */ ```
/* Regulator device name */
const char *name = "regulator_virtual_1"; const char *name = "regulator_virtual_1";
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -128,48 +121,45 @@ if (handle == NULL) { ...@@ -128,48 +121,45 @@ if (handle == NULL) {
} }
``` ```
### Closing a Regulator Device Handle<a name="section3.3_REGULATOR_des"></a> #### Closing a Regulator Device Handle
Call **RegulatorClose** to close the regulator device handle to release resources. Call **RegulatorClose** to close the regulator device handle to release resources.
```c ```
void RegulatorClose(DevHandle handle); void RegulatorClose(DevHandle handle);
``` ```
**Table 3** Description of RegulatorClose **Table 3** Description of RegulatorClose
<a name="table3_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ------ | ----------------- | | ------ | ----------------- |
| handle | Regulator device handle to close.| | handle | Device handle of the target regulator.|
```
```c
/* Close the regulator device handle. */ /* Close the regulator device handle. */
RegulatorClose(handle); RegulatorClose(handle);
``` ```
### Enabling a Regulator<a name="section3.4_REGULATOR_des"></a> #### Enabling a Regulator
Call **RegulatorEnable** to enable a regulator. Call **RegulatorEnable()** to enable a regulator.
```c ```
int32_t RegulatorEnable(DevHandle handle); int32_t RegulatorEnable(DevHandle handle);
``` ```
**Table 4** Description of RegulatorEnable **Table 4** Description of RegulatorEnable
<a name="table4_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
| handle | Device handle of the regulator to enable.| | handle | Device handle of the target regulator.|
| **Return Value**| **Description** | | **Return Value**| **Description** |
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c
```
int32_t ret; int32_t ret;
/* Enable the regulator. */ /* Enable the regulator. */
...@@ -179,26 +169,24 @@ if (ret != 0) { ...@@ -179,26 +169,24 @@ if (ret != 0) {
} }
``` ```
### Disabling a Regulator<a name="section3.5_REGULATOR_des"></a> #### Disabling a Regulator
Call **RegulatorDisable** to disable a regulator. The operation will fail if the regulator status is set to always on or if a child node of the regulator is not disabled. Call **RegulatorDisable()** to disable a regulator. The operation will fail if the regulator status is set to always on or a child node of the regulator is not disabled.
```c ```
int32_t RegulatorDisable(DevHandle handle); int32_t RegulatorDisable(DevHandle handle);
``` ```
**Table 5** Description of RegulatorDisable **Table 5** Description of RegulatorDisable
<a name="table5_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
| handle | Device handle of the regulator to disable.| | handle | Device handle of the target regulator.|
| **Return Value**| **Description** | | **Return Value**| **Description** |
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
/* Disable the regulator. */ /* Disable the regulator. */
...@@ -208,46 +196,44 @@ if (ret != 0) { ...@@ -208,46 +196,44 @@ if (ret != 0) {
} }
``` ```
### Forcibly Disabling a Regulator<a name="section3.6_REGULATOR_des"></a> #### Forcibly Disabling a Regulator
Call **RegulatorForceDisable** to forcibly disable a regulator. The regulator will be disabled event if its status is set to always on or its child node is still enabled. Call **RegulatorForceDisable()** to forcibly disable a regulator. The regulator will be disabled even if its status is set to always on or its child node is still enabled.
```c ```
int32_t RegulatorForceDisable(DevHandle handle); int32_t RegulatorForceDisable(DevHandle handle);
``` ```
**Table 6** Description of RegulatorForceDisable **Table 6** Description of RegulatorForceDisable
<a name="table6_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
| handle | Device handle of the target regulator.| | handle | Device handle of the target regulator.|
| **Return Value**| **Description** | | **Return Value**| **Description** |
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
/* Forcibly disable the regulator. */ /* Forcibly disable the regulator. /*
ret = RegulatorForceDisable(handle); ret = RegulatorForceDisable(handle);
if (ret != 0) { if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
### Setting the Output Voltage Range for a Regulator<a name="section3.7_REGULATOR_des"></a>
#### Setting the Output Voltage Range
Call **RegulatorSetVoltage** to set the output voltage range for a regulator. Call **RegulatorSetVoltage** to set the output voltage range for a regulator.
```c ```
int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv); int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv);
``` ```
**Table 7** Description of RegulatorSetVoltage **Table 7** Description of RegulatorSetVoltage
<a name="table7_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
| handle | Device handle of the target regulator.| | handle | Device handle of the target regulator.|
...@@ -257,28 +243,28 @@ int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv); ...@@ -257,28 +243,28 @@ int32_t RegulatorSetVoltage(DevHandle handle, uint32_t minUv, uint32_t maxUv);
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
int32_t minUv = 0; // Set the minimum voltage to 0 µV. int32_t minUv = 0; // The minimum voltage is 0 µV.
int32_t maxUv = 20000; // Set the maximum voltage to 20000 µV. int32_t maxUv = 20000; // The maximum voltage is 20000 µV.
/* Set the output voltage range for the regulator. */ /* Set the output voltage range of the regulator. */
ret = RegulatorSetVoltage(handle, minUv, maxUv); ret = RegulatorSetVoltage(handle, minUv, maxUv);
if (ret != 0) { if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
### Obtaining Regulator Voltage Information<a name="section3.8_REGULATOR_des"></a>
Call **RegulatorGetVoltage** to obtain voltage information of a regulator. #### Obtaining the Regulator Voltage
Call **RegulatorGetVoltage()** to obtain the regulator voltage.
```c ```
int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage); int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage);
``` ```
**Table 8** Description of RegulatorGetVoltage **Table 8** Description of RegulatorGetVoltage
<a name="table8_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
...@@ -288,30 +274,27 @@ int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage); ...@@ -288,30 +274,27 @@ int32_t RegulatorGetVoltage(DevHandle handle, uint32_t *voltage);
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
uint32_t voltage; uint32_t voltage;
/* Obtain the regulator voltage information. */ /* Obtain the regulator voltage. */
ret = RegulatorGetVoltage(handle, &voltage); ret = RegulatorGetVoltage(handle, &voltage);
if (ret != 0) { if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
#### Setting the Output Current Range
### Setting the Output Current Range for a Regulator<a name="section3.9_REGULATOR_des"></a> Call **RegulatorSetCurrent()** to set the output current range of the regulator.
Call **RegulatorSetCurrent** to set the output current range for a regulator.
```c ```
int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa); int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa);
``` ```
**Table 9** Description of RegulatorSetCurrent **Table 9** Description of RegulatorSetCurrent
<a name="table9_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
| handle | Device handle of the target regulator.| | handle | Device handle of the target regulator.|
...@@ -321,30 +304,28 @@ int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa); ...@@ -321,30 +304,28 @@ int32_t RegulatorSetCurrent(DevHandle handle, uint32_t minUa, uint32_t maxUa);
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
int32_t minUa = 0; // Set the minimum current to 0 μA. int32_t minUa = 0; // The minimum current is 0 μA.
int32_t maxUa = 200; // Set the maximum current to 200 μA. int32_t maxUa = 200; // The maximum current is 200 μA.
/* Set the output current range for the regulator. */ /* Set the output current range of the regulator. */
ret = RegulatorSetCurrent(handle, minUa, maxUa); ret = RegulatorSetCurrent(handle, minUa, maxUa);
if (ret != 0) { if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
### Obtaining Regulator Current Information<a name="section3.10_REGULATOR_des"></a> #### Obtaining the Regulator Current
Call **RegulatorGetCurrent** to obtain current information of a regulator. Call **RegulatorGetCurrent()** to obtain the current of the regulator.
```c ```
int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent); int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent);
``` ```
**Table 10** Description of RegulatorGetCurrent **Table 10** Description of RegulatorGetCurrent
<a name="table10_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ----------- | ----------------- | | ----------- | ----------------- |
| handle | Device handle of the target regulator.| | handle | Device handle of the target regulator.|
...@@ -353,28 +334,27 @@ int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent); ...@@ -353,28 +334,27 @@ int32_t RegulatorGetCurrent(DevHandle handle, uint32_t *regCurrent);
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
uint32_t regCurrent; uint32_t regCurrent;
/* Obtain the regulator current information. */ /* Obtain the current of the regulator. */
ret = RegulatorGetCurrent(handle, &regCurrent); ret = RegulatorGetCurrent(handle, &regCurrent);
if (ret != 0) { if (ret != 0) {
/* Error handling. */ /* Error handling. */
} }
``` ```
### Obtaining Regulator Status<a name="section3.11_REGULATOR_des"></a>
Call **RegulatorGetStatus** to obtain the regulator status. #### Obtaining the Regulator Status
Call **RegulatorGetStatus()** to obtain the regulator status.
```c ```
int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status); int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status);
``` ```
**Table 11** Description of RegulatorGetStatus **Table 11** Description of RegulatorGetStatus
<a name="table11_REGULATOR_des"></a>
| **Parameter** | **Description** | | **Parameter** | **Description** |
| ---------- | ----------------- | | ---------- | ----------------- |
| handle | Device handle of the target regulator.| | handle | Device handle of the target regulator.|
...@@ -383,7 +363,7 @@ int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status); ...@@ -383,7 +363,7 @@ int32_t RegulatorGetStatus(DevHandle handle, uint32_t *status);
| 0 | The operation is successful. | | 0 | The operation is successful. |
| Negative value | The operation fails. | | Negative value | The operation fails. |
```c ```
int32_t ret; int32_t ret;
uint32_t status; uint32_t status;
...@@ -394,16 +374,18 @@ if (ret != 0) { ...@@ -394,16 +374,18 @@ if (ret != 0) {
} }
``` ```
## Development Example<a name="section4_REGULATOR_des"></a>
## Development Example
The following is an example of using a regulator. The following is an example of using a regulator.
```c ```
void RegulatorTestSample(void) void RegulatorTestSample(void)
{ {
int32_t ret; int32_t ret;
/* Regulator name. */ /* Regulator device name */
const char *name = "regulator_virtual_1"; const char *name = "regulator_virtual_1";
DevHandle handle = NULL; DevHandle handle = NULL;
...@@ -421,10 +403,10 @@ void RegulatorTestSample(void) ...@@ -421,10 +403,10 @@ void RegulatorTestSample(void)
goto _ERR; goto _ERR;
} }
int32_t minUv = 0; // Set the minimum voltage to 0 µV. int32_t minUv = 0; // The minimum voltage is 0 µV.
int32_t maxUv = 20000; // Set the maximum voltage to 20000 µV. int32_t maxUv = 20000; // The maximum voltage is 20000 µV.
/* Set the output voltage range for the regulator. */ /* Set the output voltage range of the regulator. */
ret = RegulatorSetVoltage(handle, minUv, maxUv); ret = RegulatorSetVoltage(handle, minUv, maxUv);
if (ret != 0) { if (ret != 0) {
HDF_LOGE("RegulatorSetVoltage: failed, ret %d\n", ret); HDF_LOGE("RegulatorSetVoltage: failed, ret %d\n", ret);
...@@ -433,7 +415,7 @@ void RegulatorTestSample(void) ...@@ -433,7 +415,7 @@ void RegulatorTestSample(void)
uint32_t voltage; uint32_t voltage;
/* Obtain the regulator voltage information. */ /* Obtain the regulator voltage. */
ret = RegulatorGetVoltage(handle, &voltage); ret = RegulatorGetVoltage(handle, &voltage);
if (ret != 0) { if (ret != 0) {
HDF_LOGE("RegulatorGetVoltage: failed, ret %d\n", ret); HDF_LOGE("RegulatorGetVoltage: failed, ret %d\n", ret);
......
# Regulator<a name="title_REGULATORDevelop"></a> # Regulator
## Overview<a name="section1_REGULATORDevelop"></a> ## Overview
The regulator module controls the voltage and current supplies of some devices in the system. In the Hardware Driver Foundation (HDF), the regulator module uses the unified service mode for API adaptation. In this mode, a device service is used as the regulator 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 regulator has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and more memory resources will be consumed by services. ### Regulator
The regulator module controls the voltage and current supplies of some devices in the system.
### Basic Concepts
The regulator module controls the voltage and current supplies of some devices in the system. In an embedded system (especially a mobile phone), it is important to control the power consumption, which directly affects the battery endurance. You can use a regulator to shut down the power supply to an idle module in the system or reduce the voltage and current for the module.
### Working Principles
In the Hardware Driver Foundation (HDF), the regulator module uses the unified service mode for API adaptation. In this mode, a device service is used as the regulator 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 regulator has more than 10 controllers. If the independent service mode is used, more device nodes need to be configured and more memory resources will be consumed by services.
The regulator module is divided into the following layers:
- The interface layer provides APIs for opening or closing a device and writing data.
- The core layer provides the capabilities of binding, initializing, and releasing devices.
- The adaptation layer implements other functions.
![](../public_sys-resources/icon-note.gif)NOTE<br/>The core layer can call the functions of the interface layer and uses the hook to call functions of the adaptation layer. In this way, the adaptation layer can indirectly call the functions of the interface layer, but the interface layer cannot call the functions of the adaptation layer.
**Figure 1** Unified service mode **Figure 1** Unified service mode
![image1](figures/unified-service-mode.png) ![image1](figures/unified-service-mode.png)
## Available APIs<a name="section2_REGULATORDevelop"></a>
### Constraints
Currently, the regulator module supports only the kernels (LiteOS) of mini and small systems.
## Development Guidelines
### When to Use
The regulator module controls the voltage and current supplies of some devices in the system.
### Available APIs
The functions in **RegulatorMethod** are used to call the corresponding regulator driver functions:
**RegulatorMethod** structure: **RegulatorMethod** structure:
```c ```
struct RegulatorMethod { struct RegulatorMethod {
int32_t (*open)(struct RegulatorNode *node); int32_t (*open)(struct RegulatorNode *node);
int32_t (*close)(struct RegulatorNode *node); int32_t (*close)(struct RegulatorNode *node);
...@@ -28,87 +61,80 @@ struct RegulatorMethod { ...@@ -28,87 +61,80 @@ struct RegulatorMethod {
}; };
``` ```
**Table 1** APIs for the members in the RegulatorMethod structure **Table 1** Description of the RegulatorMethod structure
| Method | Input Parameter | Return Value| Description|
| ------------ | ------------------------------------------- | ------ | ---- | | Method | Input Parameter | Return Value | Description |
| open | **node**: structure pointer to the regulator node at the core layer.|HDF_STATUS|Opens a device.| | ------------ | ------------------------------------------------------------ | ------------------ | ---------------- |
| close | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Closes a device.| | open | **node**: structure pointer to the regulator node at the core layer. | HDF_STATUS| Opens a device. |
| release | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Releases a device handle.| | close | **node**: structure pointer to the regulator node at the core layer. | HDF_STATUS| Closes a device. |
| enable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Enables a device.| | release | **node**: structure pointer to the regulator node at the core layer. | HDF_STATUS| Releases a device handle. |
| disable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Disables a device.| | enable | **node**: structure pointer to the regulator node at the core layer. | HDF_STATUS| Enabling a Regulator |
| forceDisable | **node**: structure pointer to the regulator node at the core layer.| HDF_STATUS| Forcibly disables a device.| | disable | **node**: structure pointer to the regulator node at the core layer. | HDF_STATUS| Disabling a Regulator |
| forceDisable | **node**: structure pointer to the regulator node at the core layer. | HDF_STATUS| Forcibly Disabling a Regulator |
| setVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**minUv**: minimum voltage to set. It is a uint32_t variable.<br>**maxUv**: maximum voltage to set. It is a uint32_t variable.| HDF_STATUS| Sets the output voltage range.| | setVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**minUv**: minimum voltage to set. It is a uint32_t variable.<br>**maxUv**: maximum voltage to set. It is a uint32_t variable.| HDF_STATUS| Sets the output voltage range.|
| getVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**voltage**: pointer to the output voltage value.| HDF_STATUS| Obtains the voltage.| | getVoltage | **node**: structure pointer to the regulator node at the core layer.<br>**voltage**: pointer to the output voltage value.| HDF_STATUS| Obtains the voltage. |
| setCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**minUa**: minimum current to set. It is a uint32_t variable.<br>**maxUa**: maximum current to set. It is a uint32_t variable.| HDF_STATUS| Sets the output current range.| | setCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**minUa**: minimum current to set. It is a uint32_t variable.<br>**maxUa**: maximum current to set. It is a uint32_t variable.| HDF_STATUS| Sets the output current range.|
| getCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current.| | getCurrent | **node**: structure pointer to the regulator node at the core layer.<br>**regCurrent**: pointer to the output current, which is of the uint32_t type.| HDF_STATUS| Obtains the current. |
| getStatus | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status.| | getStatus | **node**: structure pointer to the regulator node at the core layer.<br>**status**: pointer to the output status, which is of the uint32_t type.| HDF_STATUS| Obtains the device status. |
## How to Develop<a name="section3_REGULATORDevelop"></a>
The regulator module adaptation involves the following steps:
1. Instantiate the driver entry.
- Instantiate the **HdfDriverEntry** structure.
- Call **HDF_INIT** to register the **HdfDriverEntry** instance with the HDF.
2. Configure attribute files.
- Add the **deviceNode** information to the **device_info.hcs** file. ### How to Develop
- (Optional) Add the **regulator_config.hcs** file.
3. Instantiate the regulator controller object. The regulator module adaptation procedure is as follows:
- Initialize **RegulatorNode** members.
- Instantiate **RegulatorMethod**.
>![](../public_sys-resources/icon-note.gif) **NOTE**
>For details, see [Available APIs](#availableapis).
4. Debug the driver.
- (Optional) Verify basic functionalities of new drivers. For example, verify the information returned when the driver is loaded and whether data is successfully transmitted.
## Development Example<a name="section4_REGULATORDevelop"></a> - Instantiate the driver entry.
- Configure attribute files.
- Instantiate the core layer APIs.
- Debug the driver.
The following uses **regulator_virtual.c** as an example to present the content to be provided by the vendor to implement device functionalities. 1. Instantiate the driver entry.
1. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf\_device\_desc.h**), and the value of **moduleName** must be the same as that in **device\_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke. Instantiate the driver entry. The driver entry must be a global variable of the **HdfDriverEntry** type (defined in **hdf_device_desc.h**), and the value of **moduleName** must be the same as that in **device_info.hcs**. In the HDF, the start address of each **HdfDriverEntry** object of all loaded drivers are collected to form a segment address space similar to an array for the upper layer to invoke.
Generally, the HDF calls the **Init()** function to load the driver. If **Init()** fails to be called, the HDF calls **Release** to release driver resources and exit.
```
struct HdfDriverEntry g_regulatorDriverEntry = {
.moduleVersion = 1,
.moduleName = "virtual_regulator_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.Init = VirtualRegulatorInit,
.Release = VirtualRegulatorRelease,
};
// Call HDF_INIT to register the driver entry with the HDF framework.
HDF_INIT(g_regulatorDriverEntry);
```
2. Configure attribute files.
Generally, the HDF calls the **Bind** function and then the **Init** function to load the driver. If **Init** fails to be called, the HDF calls **Release** to release driver resources and exit. - Add the device node description to the **vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs** file.
Regulator driver entry reference: 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 **RegulatorNode** members at the core layer.
```c In the unified service mode, the first device node in the **device_info.hcs** file must be the regulator manager. The parameters must be set as follows:
struct HdfDriverEntry g_regulatorDriverEntry = {
.moduleVersion = 1,
.moduleName = "virtual_regulator_driver",// (Mandatory) The value must be the same as that of moduleName in the .hcs file.
.Init = VirtualRegulatorInit,
.Release = VirtualRegulatorRelease,
};
// Call HDF_INIT to register the driver entry with the HDF framework.
HDF_INIT(g_regulatorDriverEntry);
```
2. Add **deviceNode** to the **device\_info.hcs** file, and set the device attributes in the **regulator\_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 **RegulatorNode** members at the core layer. | Member | Value |
| --------------- | ------------------------------------------------------------ |
| policy | **0**, which indicates that no service is published. |
| priority | Driver startup priority. The value range is 0 to 200. A larger value indicates a lower priority. If the priorities are the same, the device loading sequence is not ensured.|
| permission | Driver permission. |
| moduleName | The value is **HDF_PLATFORM_REGULATOR_MANAGER**. |
| serviceName | The value is **HDF_PLATFORM_REGULATOR_MANAGER**. |
| deviceMatchAttr | Reserved. |
>![](W:\doc\docs\en\device-dev\public_sys-resources\icon-note.gif) **NOTE** Configure regulator controller information from the second node. This node specifies a type of regulator controllers rather than a specific regulator controller. In this example, there is only one regulator device. If there are multiple regulator devices, you need to add the **deviceNode** information to the **device_info** file and add the corresponding device attributes to the **regulator\_config** file.
>If there are multiple devices, add the **deviceNode** information to the **device\_info** file and add the corresponding device attributes to the **regulator\_config** file.
- **device\_info.hcs** reference: - **device_info.hcs** configuration reference
```c ```
root { root {
device_info { device_info {
platform :: host { platform :: host {
hostName = "platform_host"; hostName = "platform_host";
priority = 50; priority = 50;
device_regulator :: device { device_regulator :: device {
device0 :: deviceNode { // Configure an HDF device node for each regulator controller. device0 :: deviceNode { // Configure an HDF device node for each regulator controller.
policy = 1; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required. policy = 1; // 2: visible in user mode; 1: visible in kernel mode; 0: no service required.
priority = 50; // Driver startup priority. priority = 50; // Driver startup priority.
permission = 0644; // Permission to create device nodes of the driver. permission = 0644; // Permission to create device nodes of the driver.
/* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */ /* (Mandatory) Driver name, which must be the same as the moduleName in the driver entry. */
moduleName = "HDF_PLATFORM_REGULATOR_MANAGER"; moduleName = "HDF_PLATFORM_REGULATOR_MANAGER";
...@@ -126,211 +152,197 @@ The following uses **regulator_virtual.c** as an example to present the content ...@@ -126,211 +152,197 @@ The following uses **regulator_virtual.c** as an example to present the content
} }
} }
} }
} }
``` ```
- **regulator\_config.hcs** reference: - **regulator\_config.hcs** reference:
```c ```
root { root {
platform { platform {
regulator_config { regulator_config {
match_attr = "linux_regulator_adapter"; match_attr = "linux_regulator_adapter";
template regulator_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes. template regulator_controller { // (Mandatory) Template configuration. In the template, you can configure the common parameters shared by device nodes.
device_num = 1; device_num = 1;
name = ""; name = "";
devName = "regulator_adapter_consumer01"; devName = "regulator_adapter_consumer01";
supplyName = ""; supplyName = "";
mode = 1; mode = 1;
minUv = 0; minUv = 0;
maxUv = 20000; maxUv = 20000;
minUa = 0; minUa = 0;
maxUa = 0; maxUa = 0;
} }
controller_0x130d0000 :: regulator_controller { controller_0x130d0000 :: regulator_controller {
device_num = 1; device_num = 1;
name = "regulator_adapter_1"; name = "regulator_adapter_1";
devName = "regulator_adapter_consumer01"; devName = "regulator_adapter_consumer01";
supplyName = "virtual-regulator-hdf-adapter"; supplyName = "virtual-regulator-hdf-adapter";
mode = 1; mode = 1;
minUv = 1000; minUv = 1000;
maxUv = 50000; maxUv = 50000;
minUa = 0; minUa = 0;
maxUa = 0; maxUa = 0;
} }
/* Each regulator controller corresponds to a controller node. If there are multiple regulator controllers, add the corresponding controller nodes one by one.*/ /* Each regulator controller corresponds to a controller node. If there are multiple regulator controllers, add the corresponding controller nodes one by one.*/
controller_0x130d0001 :: regulator_controller { controller_0x130d0001 :: regulator_controller {
device_num = 1; device_num = 1;
name = "regulator_adapter_2"; name = "regulator_adapter_2";
devName = "regulator_adapter_consumer01"; devName = "regulator_adapter_consumer01";
supplyName = "virtual2-regulator-hdf-adapter"; supplyName = "virtual2-regulator-hdf-adapter";
mode = 2; mode = 2;
minUv = 0; minUv = 0;
maxUv = 0; maxUv = 0;
minUa = 1000; minUa = 1000;
maxUa = 50000; maxUa = 50000;
} }
} }
} }
} }
``` ```
3. Initialize the **RegulatorNode** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **RegulatorMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**). 3. Instantiate the APIs of the core layer.
- Initializing the vendor custom structure - Initialize the **RegulatorNode** object at the core layer, including initializing the vendor custom structure (passing parameters and data), instantiating **RegulatorMethod** (used to call underlying functions of the driver) in **PinCntlr**, and implementing the **HdfDriverEntry** member functions (**Bind**, **Init**, and **Release**).
The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator\_config.hcs** using **DeviceResourceIface**. - Initializing the vendor custom structure
```c The **RegulatorNode** structure holds parameters and data for the driver. The HDF obtains the values in **regulator\_config.hcs** using **DeviceResourceIface**.
// RegulatorNode is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct RegulatorNode { ```
struct RegulatorDesc regulatorInfo; // RegulatorNode is the controller structure at the core layer. Its members are assigned with values by using the Init function.
struct DListHead node; struct RegulatorNode {
struct RegulatorMethod *ops; struct RegulatorDesc regulatorInfo;
void *priv; struct DListHead node;
struct OsalMutex lock; struct RegulatorMethod *ops;
}; void *priv;
struct OsalMutex lock;
struct RegulatorDesc { };
const char *name; /* Regulator name. */
const char *parentName; /* Regulator parent node name. */ struct RegulatorDesc {
struct RegulatorConstraints constraints; /* Regulator constraint information. */ const char *name; /* Regulator name. */
uint32_t minUv; /* Minimum output voltage. */ const char *parentName; /* Regulator parent node name. */
uint32_t maxUv; /* Maximum output voltage. */ struct RegulatorConstraints constraints; /* Regulator constraint information. */
uint32_t minUa; /* Minimum output current. */ uint32_t minUv; /* Minimum output voltage. */
uint32_t maxUa; /* Maximum output current. */ uint32_t maxUv; /* Maximum output voltage. */
uint32_t status; /* Regulator status, which can be on or off. */ uint32_t minUa; /* Minimum output current. */
int useCount; uint32_t maxUa; /* Maximum output current. */
int consumerRegNums; /* Number of regulator consumers. */ uint32_t status; /* Regulator status, which can be on or off. */
RegulatorStatusChangecb cb; /* Variable used to notify the regulator status changes. */ int useCount;
}; int consumerRegNums; /* Number of regulator consumers. */
RegulatorStatusChangecb cb; /* Variable used to notify the regulator status changes. */
struct RegulatorConstraints { };
uint8_t alwaysOn; /* Whether the regulator is always on. */
uint8_t mode; /* Voltage or current. */ struct RegulatorConstraints {
uint32_t minUv; /* Minimum output voltage allowed. */ uint8_t alwaysOn; /* Whether the regulator is always on. */
uint32_t maxUv; /* Maximum output voltage allowed. */ uint8_t mode; /* Voltage or current. */
uint32_t minUa; /* Minimum output current allowed. */ uint32_t minUv; /* Minimum output voltage allowed. */
uint32_t maxUa; /* Maximum output current allowed. */ uint32_t maxUv; /* Maximum output voltage allowed. */
}; uint32_t minUa; /* Minimum output current allowed. */
``` uint32_t maxUa; /* Maximum output current allowed. */
};
- Instantiating **RegulatorMethod** (other members are initialized by **Init**) ```
```c
// Example of regulator_virtual.c: Instantiate the hook.
static struct RegulatorMethod g_method = { - Instantiating **RegulatorMethod** (other members are initialized by **Init**)
.enable = VirtualRegulatorEnable,
.disable = VirtualRegulatorDisable, ```c
.setVoltage = VirtualRegulatorSetVoltage, // Example of regulator_virtual.c: Instantiate the hook.
.getVoltage = VirtualRegulatorGetVoltage, static struct RegulatorMethod g_method = {
.setCurrent = VirtualRegulatorSetCurrent, .enable = VirtualRegulatorEnable,
.getCurrent = VirtualRegulatorGetCurrent, .disable = VirtualRegulatorDisable,
.getStatus = VirtualRegulatorGetStatus, .setVoltage = VirtualRegulatorSetVoltage,
}; .getVoltage = VirtualRegulatorGetVoltage,
``` .setCurrent = VirtualRegulatorSetCurrent,
.getCurrent = VirtualRegulatorGetCurrent,
- **Init** function .getStatus = VirtualRegulatorGetStatus,
};
Input parameters: ```
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value: - **Init** function
**HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.) Input parameters:
**Table 2** HDF\_STATUS **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
<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>State</p> Return value:
</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> **HDF\_STATUS** (The following table lists some states. For more details, see **HDF\_STATUS** in **/drivers/framework/include/utils/hdf\_base.h**.)
</th>
</tr> **Table 2** HDF\_STATUS
</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> | State | Description |
</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> | HDF_ERR_INVALID_OBJECT | Invalid controller object.|
</td> | HDF_ERR_MALLOC_FAIL | Failed to allocate memory. |
</tr> | HDF_ERR_INVALID_PARAM | Invalid parameter. |
<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> | HDF_ERR_IO | I/O error. |
</td> | HDF_SUCCESS | Initialization successful. |
<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> | HDF_FAILURE | Initialization failed. |
</td>
</tr> Function description:
<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> Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer.
<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> ```c
<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> static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device)
</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> int32_t ret;
</td> const struct DeviceResourceNode *childNode = NULL;
</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> DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
</td> ret = VirtualRegulatorParseAndInit(device, childNode);// (Mandatory) The implementation is as follows:
<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> static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
</td> {
</tr> int32_t ret;
</tbody> struct RegulatorNode *regNode = NULL;
</table> (void)device;
Function description:
Initializes the custom structure and **RegulatorNode** members, and adds the regulator controller by calling the **RegulatorNodeAdd** function at the core layer. regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));// Load the .hcs file.
...
```c ret = VirtualRegulatorReadHcs(regNode, node);// Read .hcs information.
static int32_t VirtualRegulatorInit(struct HdfDeviceObject *device) ...
{ regNode->priv = (void *)node; // Instantiate the node.
int32_t ret; regNode->ops = &g_method; // Instantiate OPS.
const struct DeviceResourceNode *childNode = NULL;
... ret = RegulatorNodeAdd(regNode); // Add the node.
DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { ...
ret = VirtualRegulatorParseAndInit(device, childNode);// (Mandatory) The implementation is as follows: }
... ```
}
... - **Release** function
}
Input parameters:
static int32_t VirtualRegulatorParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
{ **HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
int32_t ret;
struct RegulatorNode *regNode = NULL; Return value:
(void)device;
regNode = (struct RegulatorNode *)OsalMemCalloc(sizeof(*regNode));// Load the .hcs file.
... Function description:
ret = VirtualRegulatorReadHcs(regNode, node);// Read .hcs information.
... Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init()** function to initialize the driver, the **Release()** function can be called to release driver resources.
regNode->priv = (void *)node; // Instantiate the node.
regNode->ops = &g_method; // Instantiate OPS.
ret = RegulatorNodeAdd(regNode); // Add the node.
...
}
- **Release** function
Input parameters:
**HdfDeviceObject**, an interface parameter exposed by the driver, contains the .hcs configuration.
Return value:
Function description:
Releases memory and deletes the controller. This function assigns a value to the **Release** API in the driver entry structure. If the HDF fails to call the **Init** function to initialize the driver, the **Release** function can be called to release driver resources.
```c ```c
static void VirtualRegulatorRelease(struct HdfDeviceObject *device) static void VirtualRegulatorRelease(struct HdfDeviceObject *device)
{ {
... ...
RegulatorNodeRemoveAll();// (Mandatory) Call the function at the core layer to release regulator controller devices and services. RegulatorNodeRemoveAll();// (Mandatory) Call the function at the core layer to release regulator controller devices and services.
} }
```
4. Debug the driver.
(Optional) Verify the basic functions of the new driver, for example, whether the test cases are successful after the driver is loaded.
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
- **[ADC](driver-platform-adc-des.md)** - **[ADC](driver-platform-adc-des.md)**
- **[DAC](driver-platform-dac-des.md)**
- **[GPIO](driver-platform-gpio-des.md)** - **[GPIO](driver-platform-gpio-des.md)**
- **[HDMI](driver-platform-hdmi-des.md)** - **[HDMI](driver-platform-hdmi-des.md)**
...@@ -14,6 +16,8 @@ ...@@ -14,6 +16,8 @@
- **[MIPI DSI](driver-platform-mipidsi-des.md)** - **[MIPI DSI](driver-platform-mipidsi-des.md)**
- **[Pin](driver-platform-pin-des.md)**
- **[PWM](driver-platform-pwm-des.md)** - **[PWM](driver-platform-pwm-des.md)**
- **[RTC](driver-platform-rtc-des.md)** - **[RTC](driver-platform-rtc-des.md)**
......
# Source Code Acquisition # Source Code Acquisition
- [Source Code Acquisition](sourcecode-acquire.md) - [Obtaining Source Code](sourcecode-acquire.md)
- [Tool Acquisition](gettools.md) - Obtaining Tools
- [Docker Environment](gettools-acquire.md) - [Overview](gettools-overview.md)
- [IDE](gettools-ide.md) - [Docker Environments](gettools-acquire.md)
- [IDE](gettools-ide.md)
...@@ -166,7 +166,7 @@ Files generated during building are stored in the **out/{device_name}/** direc ...@@ -166,7 +166,7 @@ Files generated during building are stored in the **out/{device_name}/** direc
## HPM-based Docker Environment<a name="section485713518337"></a> ## HPM-based Docker Environment<a name="section485713518337"></a>
**docker\_dist** is a template component in the [HPM](https://hpm.harmonyos.com/#/en/home) system. It helps to quickly initialize an HPM project and use the Docker image to quickly build a distribution of OpenHarmony, greatly simplifying environment configurations needed for building. After configuring the Ubuntu and [hpm-cli](../bundles/hpm-part-development.md) development environments, perform the following steps to access the Docker environment: **docker\_dist** is a template component in the [HPM](https://hpm.harmonyos.com/#/en/home) system. It helps to quickly initialize an HPM project and use the Docker image to quickly build a distribution of OpenHarmony, greatly simplifying environment configurations needed for building. After configuring the Ubuntu and hpm-cli development environments, perform the following steps to access the Docker environment:
### Setting Up the Docker Environment<a name="section3295842510"></a> ### Setting Up the Docker Environment<a name="section3295842510"></a>
......
# IDE<a name="EN-US_TOPIC_0000001128361880"></a> # IDE
## Acquiring the Device Development Tool \(HUAWEI DevEco Device Tool\)<a name="section2452141120244"></a> ## Acquiring the Device Development Tool \(HUAWEI DevEco Device Tool\)
HUAWEI DevEco Device Tool is a one-stop integrated development environment \(IDE\) provided to develop applications for OpenHarmony devices. It allows on-demand customization of OpenHarmony components, code editing, building, burning, and debugging, and supports C and C++ languages. This tool is installed in Visual Studio Code as a plug-in. For details, see [HUAWEI DevEco Device Tool](https://device.harmonyos.com/en/ide) and [HUAWEI DevEco Device Tool User Guide](https://device.harmonyos.com/en/docs/ide/user-guides/service_introduction-0000001050166905). HUAWEI DevEco Device Tool is a one-stop integrated development environment \(IDE\) provided to develop applications for OpenHarmony devices. It allows on-demand customization of OpenHarmony components, code editing, building, burning, and debugging, and supports C and C++ languages. This tool is installed in Visual Studio Code as a plug-in. For details, see [HUAWEI DevEco Device Tool](https://device.harmonyos.com/en/ide) and [HUAWEI DevEco Device Tool User Guide](https://device.harmonyos.com/en/docs/ide/user-guides/service_introduction-0000001050166905).
The roadmap of Huawei DevEco Device Tool for supporting OpenHarmony device development is shown in the figure below.
![](figure/evolution-roadmap.png) ## Acquiring the Application Development Tool \(HUAWEI DevEco Studio\)
## Acquiring the Application Development Tool \(HUAWEI DevEco Studio\)<a name="section0904101019258"></a> HUAWEI DevEco Studio \(DevEco Studio for short\) is a one-stop IDE oriented to Huawei devices in all scenarios. It provides E2E OpenHarmony application development services, ranging from project template creation to development, building, debugging, and release. With DevEco Studio, you will be able to efficiently develop OpenHarmony applications with distributed capabilities while speeding up innovation. For details, see [HUAWEI DevEco Studio](https://developer.harmonyos.com/en/develop/deveco-studio) and [HUAWEI DevEco Studio User Guide](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ohos-deveco-studio-overview-0000001263280421).
HUAWEI DevEco Studio \(DevEco Studio for short\) is a one-stop IDE oriented to Huawei devices in all scenarios. It provides E2E OpenHarmony application development services, ranging from project template creation to development, building, debugging, and release. With DevEco Studio, you will be able to efficiently develop OpenHarmony applications with distributed capabilities while speeding up innovation. For details, see [HUAWEI DevEco Studio](https://developer.harmonyos.com/en/develop/deveco-studio) and [HUAWEI DevEco Studio User Guide](https://developer.harmonyos.com/en/docs/documentation/doc-guides/tools_overview-0000001053582387).
# Overview
To streamline your device development process, OpenHarmony provides the useful tools listed below.
**Table 1** Tools for device development
| Tool | Description | Related Resources|
| ---- | ------ | ------ |
| DevEco Device Tool | A one-stop integrated development environment (IDE) provided for developers of OpenHarmony-powered smart devices. It allows on-demand component customization, as well as code editing, compilation, burning, and debugging. The tool supports C and C++ languages and can be installed in Visual Studio Code as a plug-in.| [HUAWEI DevEco Device Tool User Guide](https://device.harmonyos.com/en/docs/documentation/guide/service_introduction-0000001050166905)|
| Docker | A containerization platform used to build and containerize applications. The Docker environments in OpenHarmony encapsulate compilation toolchains for different OpenHarmony variants, so you can start your building straightaway without having to install the compilation toolchain on your own.| [Docker Environment](gettools-acquire.md)|
...@@ -4,16 +4,16 @@ ...@@ -4,16 +4,16 @@
OpenHarmony is an open-source project launched by the OpenAtom Foundation. The purpose of this project is to build an open, distributed operating system \(OS\) framework for smart IoT devices in the full-scenario, full-connectivity, and full-intelligence era. OpenHarmony is an open-source project launched by the OpenAtom Foundation. The purpose of this project is to build an open, distributed operating system \(OS\) framework for smart IoT devices in the full-scenario, full-connectivity, and full-intelligence era.
The open-source code repositories are available at [https://openharmony.gitee.com](https://openharmony.gitee.com). The open-source code repositories are available at [https://openharmony.gitee.com](https://openharmony.gitee.com).
## Overview of Source Code Acquisition<a name="section12763342204"></a> ## Overview of Source Code Acquisition<a name="section12763342204"></a>
You can use any of the following methods to acquire the OpenHarmony source code: You can use any of the following methods to acquire the OpenHarmony source code:
- **Method 1**: Acquire the source code from the Gitee code repository. You can use the **repo** or **git** tool to download the latest code from the code repository. - **Method 1**: Acquire the source code from the Gitee code repository. You can use the **repo** or **git** tool to download the latest code from the code repository.
- **Method 2**: Acquire the source code from [DevEco Marketplace](https://repo.harmonyos.com/#/en/home). Visit [DevEco Marketplace](https://repo.harmonyos.com/#/en/home), search for your desired open-source distribution, and download the bundle list \(or customize bundles and download the bundle list\). Then use **hpm-cli** to download and install the bundles and compilation toolchain on your local PC. - **Method 2**: Acquire the source code from [DevEco Marketplace](https://repo.harmonyos.com/#/en/home). Visit [DevEco Marketplace](https://repo.harmonyos.com/#/en/home), search for your desired open-source distribution, and download the bundle list \(or customize bundles and download the bundle list\). Then use the **hpm-cli** tool to download and install the bundles and compilation toolchain on your local PC.
- **Method 3**: Download the compressed file of a distribution from a mirror site. This method provides a fast download speed, so you can also use this method for obtaining the source code of an earlier version. - **Method 3**: Download the compressed file of a distribution from a mirror site. This method provides a fast download speed, so you can also use this method for obtaining the source code of an earlier version.
- **Method 4**: Acquire the source code from the GitHub image repository. You can use the **repo** or **git** tool to download the latest code from the code repository. - **Method 4**: Acquire the source code from the GitHub image repository. You can use the **repo** or **git** tool to download the latest code from the code repository.
## Method 1: Acquiring Source Code from the Gitee Code Repository<a name="section537312010229"></a> ## Method 1: Acquiring Source Code from the Gitee Code Repository<a name="section537312010229"></a>
...@@ -34,7 +34,7 @@ You can use any of the following methods to acquire the OpenHarmony source code: ...@@ -34,7 +34,7 @@ You can use any of the following methods to acquire the OpenHarmony source code:
1. Register your account with Gitee. 1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee. 2. Register an SSH public key for access to Gitee.
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. 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" git config --global user.name "yourname"
...@@ -42,10 +42,10 @@ You can use any of the following methods to acquire the OpenHarmony source code: ...@@ -42,10 +42,10 @@ You can use any of the following methods to acquire the OpenHarmony source code:
git config --global credential.helper store git config --global credential.helper store
``` ```
4. Run the following commands to install the **repo** tool: 4. Run the following commands to install the **repo** tool:
``` ```
curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable. curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
``` ```
...@@ -53,14 +53,13 @@ You can use any of the following methods to acquire the OpenHarmony source code: ...@@ -53,14 +53,13 @@ You can use any of the following methods to acquire the OpenHarmony source code:
### How to Use<a name="section429012478331"></a> ### How to Use<a name="section429012478331"></a>
**Obtaining the Source Code for Mini/Small/Standard Systems**
>![](../public_sys-resources/icon-note.gif) **NOTE:** >![](../public_sys-resources/icon-note.gif) **NOTE**
>Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities. >Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master code** - **Obtaining OpenHarmony master 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.\) 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 init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify
...@@ -68,7 +67,7 @@ You can use any of the following methods to acquire the OpenHarmony source code: ...@@ -68,7 +67,7 @@ You can use any of the following methods to acquire the OpenHarmony source code:
repo forall -c 'git lfs pull' repo forall -c 'git lfs pull'
``` ```
Method 2: Use the **repo** tool to download the source code over HTTPS. 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 init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify
...@@ -78,26 +77,26 @@ You can use any of the following methods to acquire the OpenHarmony source code: ...@@ -78,26 +77,26 @@ You can use any of the following methods to acquire the OpenHarmony source code:
- **Obtaining OpenHarmony release code** - **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../../release-notes/Readme.md). For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../../release-notes/Readme.md).
## Method 2: Acquiring Source Code from DevEco Marketplace<a name="section463013147412"></a> ## Method 2: Acquiring Source Code from DevEco Marketplace<a name="section463013147412"></a>
### When to Use<a name="section26661067443"></a> ### When to Use<a name="section26661067443"></a>
If OpenHarmony is new to you, sample solutions are helpful to your development. You can obtain an open-source distribution from [DevEco Marketplace](https://repo.harmonyos.com/#/en/home), or customize a distribution by adding or deleting bundles of an open-source distribution. Then use **hpm-cli** to download and install the bundles and compilation toolchain on your local PC. If OpenHarmony is new to you, sample solutions are helpful to your development. You can obtain an open-source distribution from [DevEco Marketplace](https://repo.harmonyos.com/#/en/home), or customize a distribution by adding or deleting bundles of an open-source distribution. Then use the **hpm-cli** tool to download and install the bundles and compilation toolchain on your local PC.
### Prerequisites<a name="section17544943123315"></a> ### Prerequisites<a name="section17544943123315"></a>
You must install **Node.js** and HPM on your local PC. The installation procedure is as follows: You must install **Node.js** and HPM on your local PC. The installation procedure is as follows:
1. Install **Node.js**. 1. Install **Node.js**.
Download **Node.js** from its official website and install it on your local PC. Download **Node.js** from its official website and install it on your local PC.
The [Node.js](https://nodejs.org/) version must be 12.x \(including npm 6.14.4\) or later. An LTS version is recommended. The [Node.js](https://nodejs.org/) version must be 12.x \(including npm 6.14.4\) or later. An LTS version is recommended.
2. Install the hpm-cli tool using **npm** delivered with **Node.js**. 2. Install the **hpm-cli** tool using **npm** delivered with **Node.js**.
Open the CMD window and run the following command: Open the CMD window and run the following command:
...@@ -121,54 +120,54 @@ You must install **Node.js** and HPM on your local PC. The installation proced ...@@ -121,54 +120,54 @@ You must install **Node.js** and HPM on your local PC. The installation proced
### How to Use<a name="section954619433333"></a> ### How to Use<a name="section954619433333"></a>
1. Search for distributions. 1. Search for distributions.
1. Access [DevEco Marketplace](https://repo.harmonyos.com/#/en/home), and click **Equipment Bundle**. 1. Access [DevEco Marketplace](https://repo.harmonyos.com/#/en/home), and click **Equipment Bundle**. Then go to the **Open Source Distribution** page.
2. Enter a keyword, for example, **camera**, in the search box, and click the search icon. All matched distributions will be displayed on the **Open Source Distribution** page. 2. Enter a keyword \(for example: **camera**\) in the search box. All matched distributions are found.
3. Specify filter criteria, such as the category, OS, kernel, and board, to further filter the distributions. 3. Specify filter criteria, such as the bundle type \(for example: **Board support** or **Kernel support**\), to further filter the distributions.
4. Find your desired distribution and click it to view details. 4. Find your desired distribution and click it to view details.
**Figure 1** HPM page<a name="fig349416264520"></a> **Figure 1** HPM page<a name="fig349416264520"></a>
![](figure/hpm-page.png "hpm-page") ![](figure/hpm-page.png "hpm-page")
2. Learn more about the distribution. 2. Learn more about the distribution.
1. Read the information about the distribution to learn its application scenarios, features, bundles, usage, and customization methods, as shown in the following figure. 1. Read carefully the information about the distribution to learn its application scenarios, features, bundles, usage, and customization methods, as shown in the following figure.
2. Click **Download** to download the distribution to your local PC. 2. Click **Download** if you want to download the distribution to your local PC.
3. Click **Custom** to add or delete bundles of the distribution. 3. Click **Custom** if you want to add or delete bundles of the distribution.
**Figure 2** Example distribution<a name="fig142484411121"></a> **Figure 2** Example distribution<a name="fig142484411121"></a>
![](figure/example-distribution.png "example-distribution") ![](figure/example-distribution.png "example-distribution")
3. Customize bundles. 3. Customize bundles.
1. Access the **Custom solution** page, as shown in the following figure. 1. Access the **Custom solution** page, as shown in the following figure.
2. Set the toggle switch next to a specific optional bundle to delete it from the distribution, or click **Add bundle** to add new bundles. 2. Set the toggle switch next to a specific optional bundle to delete it from the distribution, or click **Add bundle** to add new bundles.
3. Enter the basic information about your project, including the bundle name, version, and description, on the right pane. 3. Enter the basic information about your project, including the bundle name, version, and description, on the right pane.
4. Click **Download**. The system then generates the OpenHarmony code structure file \(for example, **my\_cust\_dist.zip**\) and saves it to your local PC. 4. Click **Download**. The system generates the OpenHarmony code structure file \(for example, **my\_cust\_dist.zip**\) and saves it to your local PC.
**Figure 3** Customizing bundles<a name="fig1256020372197"></a> **Figure 3** Customizing bundles<a name="fig1256020372197"></a>
![](figure/customizing-bundles.png "customizing-bundles") ![](figure/customizing-bundles.png "customizing-bundles")
4. Install bundles. 4. Install bundles.
1. Decompress the downloaded code structure file using CMD on Windows \(or shell in Linux\). 1. Decompress the downloaded code structure file using CMD on Windows (or shell in Linux).
2. In the generated directory, run the **hpm install** command to download and install bundles. If the **Install successful** message is displayed, the command has been executed successfully. 2. In the generated directory, run the **hpm install** command to download and install bundles. If the **Install successful** message is displayed, the command has been executed successfully.
3. The downloaded bundles will be stored in the **ohos\_bundles** folder under the project directory. \(The source code of some bundles will be copied to a specified directory after the bundles are installed.\) 3. Obtain the bundles. The downloaded bundles are stored in the **ohos\_bundles** folder under the project directory. \(The source code of some bundles will be copied to a specified directory after the bundles are installed.\)
## Method 3: Acquiring Source Code from a Mirror Site<a name="section1186691118430"></a> ## Method 3: Acquiring Source Code from a Mirror Site<a name="section1186691118430"></a>
To ensure the download performance, you are advised to download the source code or the corresponding solution from the image library of the respective site listed in the table below. To ensure the download performance, you are advised to download the source code or the corresponding solution from the image library of the respective site listed in the table below.
The table below provides only the sites for downloading the latest OpenHarmony master and LTS code. For details about how to obtain the source code of earlier versions, see the [Release-Notes](../../release-notes/Readme.md). The table below provides only the sites for downloading the latest OpenHarmony LTS code. For details about how to obtain the source code of earlier versions, see the [Release-Notes](../../release-notes/Readme.md).
**Table 1** Sites for acquiring source code **Table 1** Sites for acquiring source code
<a name="table17735923173912"></a> <a name="table17735923173912"></a>
<table><thead align="left"><tr id="row1073515237392"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p5109183611392"><a name="p5109183611392"></a><a name="p5109183611392"></a><strong id="b1024917372278"><a name="b1024917372278"></a><a name="b1024917372278"></a>LTS Code</strong></p> <table><thead align="left"><tr id="row1073515237392"><th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.1"><p id="p5109183611392"><a name="p5109183611392"></a><a name="p5109183611392"></a><strong id="b31091936183918"><a name="b31091936183918"></a><a name="b31091936183918"></a>LTS Code</strong></p>
</th> </th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p13109436103916"><a name="p13109436103916"></a><a name="p13109436103916"></a><strong id="b178520552564"><a name="b178520552564"></a><a name="b178520552564"></a>Version Information</strong></p> <th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.2"><p id="p13109436103916"><a name="p13109436103916"></a><a name="p13109436103916"></a><strong id="b191091936153912"><a name="b191091936153912"></a><a name="b191091936153912"></a>Version Information</strong></p>
</th> </th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p610923616398"><a name="p610923616398"></a><a name="p610923616398"></a><strong id="b1571518441579"><a name="b1571518441579"></a><a name="b1571518441579"></a>Site</strong></p> <th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.3"><p id="p610923616398"><a name="p610923616398"></a><a name="p610923616398"></a><strong id="b1210920365393"><a name="b1210920365393"></a><a name="b1210920365393"></a>Site</strong></p>
</th> </th>
<th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p2109736133914"><a name="p2109736133914"></a><a name="p2109736133914"></a><strong id="b1777314471977"><a name="b1777314471977"></a><a name="b1777314471977"></a>SHA-256 Verification Code</strong></p> <th class="cellrowborder" valign="top" width="25%" id="mcps1.2.5.1.4"><p id="p2109736133914"><a name="p2109736133914"></a><a name="p2109736133914"></a><strong id="b18109113613397"><a name="b18109113613397"></a><a name="b18109113613397"></a>SHA-256 Verification Code</strong></p>
</th> </th>
</tr> </tr>
</thead> </thead>
...@@ -235,85 +234,85 @@ The table below provides only the sites for downloading the latest OpenHarmony m ...@@ -235,85 +234,85 @@ The table below provides only the sites for downloading the latest OpenHarmony m
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p039662242117"><a name="p039662242117"></a><a name="p039662242117"></a>-</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p039662242117"><a name="p039662242117"></a><a name="p039662242117"></a>-</p>
</td> </td>
</tr> </tr>
<tr id="row573719239393"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p104146493390"><a name="p104146493390"></a><a name="p104146493390"></a><strong id="b16812121192918"><a name="b16812121192918"></a><a name="b16812121192918"></a>Master Code</strong></p> <tr id="row573719239393"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p104146493390"><a name="p104146493390"></a><a name="p104146493390"></a><strong id="b12414104919398"><a name="b12414104919398"></a><a name="b12414104919398"></a>Latest Release Code</strong></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p194141849163919"><a name="p194141849163919"></a><a name="p194141849163919"></a><strong id="b1094411391670"><a name="b1094411391670"></a><a name="b1094411391670"></a>Version Information</strong></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p194141849163919"><a name="p194141849163919"></a><a name="p194141849163919"></a><strong id="b441494913918"><a name="b441494913918"></a><a name="b441494913918"></a>Version Information</strong></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p8414649193919"><a name="p8414649193919"></a><a name="p8414649193919"></a><strong id="b633407350"><a name="b633407350"></a><a name="b633407350"></a>Site</strong></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p8414649193919"><a name="p8414649193919"></a><a name="p8414649193919"></a><strong id="b341584914393"><a name="b341584914393"></a><a name="b341584914393"></a>Site</strong></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p13415149133914"><a name="p13415149133914"></a><a name="p13415149133914"></a><strong id="b1155996744"><a name="b1155996744"></a><a name="b1155996744"></a>SHA-256 Verification Code</strong></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p13415149133914"><a name="p13415149133914"></a><a name="p13415149133914"></a><strong id="b8415114953915"><a name="b8415114953915"></a><a name="b8415114953915"></a>SHA-256 Verification Code</strong></p>
</td> </td>
</tr> </tr>
<tr id="row18518114121312"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p4437184283419"><a name="p4437184283419"></a><a name="p4437184283419"></a>Full code base (for mini, small, and standard systems)</p> <tr id="row18518114121312"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p4437184283419"><a name="p4437184283419"></a><a name="p4437184283419"></a>Full code base (for mini, small, and standard systems)</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p15437144213345"><a name="p15437144213345"></a><a name="p15437144213345"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p15437144213345"><a name="p15437144213345"></a><a name="p15437144213345"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p64379420343"><a name="p64379420343"></a><a name="p64379420343"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/code-v3.1-Beta.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p64379420343"><a name="p64379420343"></a><a name="p64379420343"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/code-v3.1-Release.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p13437842103414"><a name="p13437842103414"></a><a name="p13437842103414"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/code-v3.1-Beta.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p13437842103414"><a name="p13437842103414"></a><a name="p13437842103414"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/code-v3.1-Release.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
</tr> </tr>
<tr id="row461814235717"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p0618124216579"><a name="p0618124216579"></a><a name="p0618124216579"></a>Hi3516 standard system solution (binary)</p> <tr id="row461814235717"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p0618124216579"><a name="p0618124216579"></a><a name="p0618124216579"></a>Hi3516 standard system solution (binary)</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p156181142145714"><a name="p156181142145714"></a><a name="p156181142145714"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p156181142145714"><a name="p156181142145714"></a><a name="p156181142145714"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p16619174275717"><a name="p16619174275717"></a><a name="p16619174275717"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/standard_hi3516.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p16619174275717"><a name="p16619174275717"></a><a name="p16619174275717"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_hi3516.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p79771324121813"><a name="p79771324121813"></a><a name="p79771324121813"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/standard_hi3516.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p79771324121813"><a name="p79771324121813"></a><a name="p79771324121813"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_hi3516.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
</tr> </tr>
<tr id="row162201392319"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p2220191315"><a name="p2220191315"></a><a name="p2220191315"></a>RK3568 standard system solution (binary)</p> <tr id="row162201392319"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p2220191315"><a name="p2220191315"></a><a name="p2220191315"></a>RK3568 standard system solution (binary)</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p6220191312"><a name="p6220191312"></a><a name="p6220191312"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p6220191312"><a name="p6220191312"></a><a name="p6220191312"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p522019916317"><a name="p522019916317"></a><a name="p522019916317"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/standard_rk3568.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p522019916317"><a name="p522019916317"></a><a name="p522019916317"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_rk3568.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p18742268187"><a name="p18742268187"></a><a name="p18742268187"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/standard_rk3568.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p18742268187"><a name="p18742268187"></a><a name="p18742268187"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/standard_rk3568.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
</tr> </tr>
<tr id="row148666201519"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p18867820165113"><a name="p18867820165113"></a><a name="p18867820165113"></a>Hi3861 solution (binary)</p> <tr id="row148666201519"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p18867820165113"><a name="p18867820165113"></a><a name="p18867820165113"></a>Hi3861 solution (binary)</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p108671520115118"><a name="p108671520115118"></a><a name="p108671520115118"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p108671520115118"><a name="p108671520115118"></a><a name="p108671520115118"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p19867202085113"><a name="p19867202085113"></a><a name="p19867202085113"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/hispark_pegasus.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p19867202085113"><a name="p19867202085113"></a><a name="p19867202085113"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_pegasus.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p193613276183"><a name="p193613276183"></a><a name="p193613276183"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/hispark_pegasus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p193613276183"><a name="p193613276183"></a><a name="p193613276183"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_pegasus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
</tr> </tr>
<tr id="row6114461545"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p630312351557"><a name="p630312351557"></a><a name="p630312351557"></a>Hi3516 solution-LiteOS (binary)</p> <tr id="row6114461545"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p630312351557"><a name="p630312351557"></a><a name="p630312351557"></a>Hi3516 solution-LiteOS (binary)</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1612646125413"><a name="p1612646125413"></a><a name="p1612646125413"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1612646125413"><a name="p1612646125413"></a><a name="p1612646125413"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p8123467546"><a name="p8123467546"></a><a name="p8123467546"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/hispark_taurus.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p8123467546"><a name="p8123467546"></a><a name="p8123467546"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p197721270187"><a name="p197721270187"></a><a name="p197721270187"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/hispark_taurus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p197721270187"><a name="p197721270187"></a><a name="p197721270187"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
</tr> </tr>
<tr id="row152143765612"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p530833917567"><a name="p530833917567"></a><a name="p530833917567"></a>Hi3516 solution-Linux (binary)</p> <tr id="row152143765612"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p530833917567"><a name="p530833917567"></a><a name="p530833917567"></a>Hi3516 solution-Linux (binary)</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p19213372563"><a name="p19213372563"></a><a name="p19213372563"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p19213372563"><a name="p19213372563"></a><a name="p19213372563"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1921337205612"><a name="p1921337205612"></a><a name="p1921337205612"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/hispark_taurus_linux.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p1921337205612"><a name="p1921337205612"></a><a name="p1921337205612"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus_linux.tar.gz" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p14441122810188"><a name="p14441122810188"></a><a name="p14441122810188"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Beta/hispark_taurus_linux.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p14441122810188"><a name="p14441122810188"></a><a name="p14441122810188"></a><a href="https://repo.huaweicloud.com/harmonyos/os/3.1-Release/hispark_taurus_linux.tar.gz.sha256" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
</tr> </tr>
<tr id="row1663285502319"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1961810962416"><a name="p1961810962416"></a><a name="p1961810962416"></a>RELEASE-NOTES</p> <tr id="row1663285502319"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1961810962416"><a name="p1961810962416"></a><a name="p1961810962416"></a>RELEASE-NOTES</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p146331255172318"><a name="p146331255172318"></a><a name="p146331255172318"></a>3.1 Beta</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p146331255172318"><a name="p146331255172318"></a><a name="p146331255172318"></a>3.1 Release</p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p18800131862419"><a name="p18800131862419"></a><a name="p18800131862419"></a><a href="https://gitee.com/openharmony/docs/tree/OpenHarmony-3.1-Beta/zh-cn/release-notes/OpenHarmony-v3.1-beta.md" target="_blank" rel="noopener noreferrer">Download</a></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p18800131862419"><a name="p18800131862419"></a><a name="p18800131862419"></a><a href="https://gitee.com/openharmony/docs/tree/OpenHarmony-3.1-Release/zh-cn/release-notes/OpenHarmony-v3.1-Release.md" target="_blank" rel="noopener noreferrer">Download</a></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p8633855132314"><a name="p8633855132314"></a><a name="p8633855132314"></a>-</p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p8633855132314"><a name="p8633855132314"></a><a name="p8633855132314"></a>-</p>
</td> </td>
</tr> </tr>
<tr id="row19937626418"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1938221842"><a name="p1938221842"></a><a name="p1938221842"></a><strong id="b1349173911553"><a name="b1349173911553"></a><a name="b1349173911553"></a>Compiler Toolchain</strong></p> <tr id="row19937626418"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p1938221842"><a name="p1938221842"></a><a name="p1938221842"></a><strong id="b1393619251243"><a name="b1393619251243"></a><a name="b1393619251243"></a>Compiler Toolchain</strong></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1093810218417"><a name="p1093810218417"></a><a name="p1093810218417"></a><strong id="b1124015405556"><a name="b1124015405556"></a><a name="b1124015405556"></a>Version Information</strong></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.2 "><p id="p1093810218417"><a name="p1093810218417"></a><a name="p1093810218417"></a><strong id="b1416114641015"><a name="b1416114641015"></a><a name="b1416114641015"></a>Version Information</strong></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p9938132648"><a name="p9938132648"></a><a name="p9938132648"></a><strong id="b863446747"><a name="b863446747"></a><a name="b863446747"></a>Site</strong></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.3 "><p id="p9938132648"><a name="p9938132648"></a><a name="p9938132648"></a><strong id="b14842143351015"><a name="b14842143351015"></a><a name="b14842143351015"></a>Site</strong></p>
</td> </td>
<td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p12520113711011"><a name="p12520113711011"></a><a name="p12520113711011"></a><strong id="b19256751175516"><a name="b19256751175516"></a><a name="b19256751175516"></a>SHA-256 Verification Code</strong></p> <td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.4 "><p id="p12520113711011"><a name="p12520113711011"></a><a name="p12520113711011"></a><strong id="b17520237181015"><a name="b17520237181015"></a><a name="b17520237181015"></a>SHA-256 Verification Code</strong></p>
</td> </td>
</tr> </tr>
<tr id="row204197817410"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p8419118242"><a name="p8419118242"></a><a name="p8419118242"></a>Compiler toolchain</p> <tr id="row204197817410"><td class="cellrowborder" valign="top" width="25%" headers="mcps1.2.5.1.1 "><p id="p8419118242"><a name="p8419118242"></a><a name="p8419118242"></a>Compiler toolchain</p>
...@@ -328,9 +327,12 @@ The table below provides only the sites for downloading the latest OpenHarmony m ...@@ -328,9 +327,12 @@ The table below provides only the sites for downloading the latest OpenHarmony m
</tbody> </tbody>
</table> </table>
## Method 4: Acquiring Source Code from the GitHub Image Repository \(at 23:00 UTC Every Day\)<a name="section23448418360"></a> ## Method 4: Acquiring Source Code from the GitHub Image Repository<a name="section23448418360"></a>
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 GitHub. For details, see [Adding a new SSH key to your GitHub account](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account).\) >![](../public_sys-resources/icon-note.gif) **NOTE**
> The image repository is synchronized at 23:00 (UTC +8:00) every day.
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 GitHub. For details, see [Adding a new SSH key to your GitHub account](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account).\)
``` ```
repo init -u git@github.com:openharmony/manifest.git -b master --no-repo-verify repo init -u git@github.com:openharmony/manifest.git -b master --no-repo-verify
...@@ -338,7 +340,7 @@ repo sync -c ...@@ -338,7 +340,7 @@ repo sync -c
repo forall -c 'git lfs pull' repo forall -c 'git lfs pull'
``` ```
Method 2: Use the **repo** tool to download the source code over HTTPS. Method 2: Use the **repo** tool to download the source code over HTTPS.
``` ```
repo init -u https://github.com/openharmony/manifest.git -b master --no-repo-verify repo init -u https://github.com/openharmony/manifest.git -b master --no-repo-verify
...@@ -350,7 +352,7 @@ repo forall -c 'git lfs pull' ...@@ -350,7 +352,7 @@ repo forall -c 'git lfs pull'
The following table describes the OpenHarmony source code directories. The following table describes the OpenHarmony source code directories.
**Table 2** Source code directories **Table 2** Source code directories
<a name="table3815144702820"></a> <a name="table3815144702820"></a>
<table><thead align="left"><tr id="row198162047192810"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p690319291299"><a name="p690319291299"></a><a name="p690319291299"></a>Name</p> <table><thead align="left"><tr id="row198162047192810"><th class="cellrowborder" valign="top" width="50%" id="mcps1.2.3.1.1"><p id="p690319291299"><a name="p690319291299"></a><a name="p690319291299"></a>Name</p>
...@@ -371,7 +373,7 @@ The following table describes the OpenHarmony source code directories. ...@@ -371,7 +373,7 @@ The following table describes the OpenHarmony source code directories.
</tr> </tr>
<tr id="row1134218692910"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p4904112910295"><a name="p4904112910295"></a><a name="p4904112910295"></a>build</p> <tr id="row1134218692910"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p4904112910295"><a name="p4904112910295"></a><a name="p4904112910295"></a>build</p>
</td> </td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1090482942911"><a name="p1090482942911"></a><a name="p1090482942911"></a>Bundle-based compilation, building, and configuration scripts</p> <td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p1090482942911"><a name="p1090482942911"></a><a name="p1090482942911"></a>Bundle-based compilation, build, and configuration scripts</p>
</td> </td>
</tr> </tr>
<tr id="row8166154261316"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1216719425130"><a name="p1216719425130"></a><a name="p1216719425130"></a>docs</p> <tr id="row8166154261316"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1216719425130"><a name="p1216719425130"></a><a name="p1216719425130"></a>docs</p>
...@@ -401,7 +403,7 @@ The following table describes the OpenHarmony source code directories. ...@@ -401,7 +403,7 @@ The following table describes the OpenHarmony source code directories.
</tr> </tr>
<tr id="row194175972917"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1904132912910"><a name="p1904132912910"></a><a name="p1904132912910"></a>prebuilts</p> <tr id="row194175972917"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p1904132912910"><a name="p1904132912910"></a><a name="p1904132912910"></a>prebuilts</p>
</td> </td>
<td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p390492919296"><a name="p390492919296"></a><a name="p390492919296"></a>Compiler and tool chain subsystem</p> <td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.2 "><p id="p390492919296"><a name="p390492919296"></a><a name="p390492919296"></a>Compiler and toolchain subsystem</p>
</td> </td>
</tr> </tr>
<tr id="row841718942913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12904929202919"><a name="p12904929202919"></a><a name="p12904929202919"></a>test</p> <tr id="row841718942913"><td class="cellrowborder" valign="top" width="50%" headers="mcps1.2.3.1.1 "><p id="p12904929202919"><a name="p12904929202919"></a><a name="p12904929202919"></a>test</p>
...@@ -431,4 +433,3 @@ The following table describes the OpenHarmony source code directories. ...@@ -431,4 +433,3 @@ The following table describes the OpenHarmony source code directories.
</tr> </tr>
</tbody> </tbody>
</table> </table>
# Bundles # HPM Part
- [HPM Part Overview](hpm-part-about.md) - [HPM Part Overview](hpm-part-about.md)
- [HPM Part Development](hpm-part-development.md) - [HPM Part Development](hpm-part-development.md)
......
...@@ -157,22 +157,22 @@ You can use the hpm-cli tool to manage the lifecycle of an HPM Part. The followi ...@@ -157,22 +157,22 @@ You can use the hpm-cli tool to manage the lifecycle of an HPM Part. The followi
| -------- | -------- | -------- | | -------- | -------- | -------- |
| Querying version information| **hpm -V** or **hpm --version**| Displays the version of the hpm-cli tool.| | Querying version information| **hpm -V** or **hpm --version**| Displays the version of the hpm-cli tool.|
| Querying help information| **hpm -h** or **hpm --version**| Displays the command list and help information.| | Querying help information| **hpm -h** or **hpm --version**| Displays the command list and help information.|
| hpm&nbsp;-h | Displays command help information.| || hpm&nbsp;-h | Displays command help information.|
| Creating a project| hpm&nbsp;init&nbsp;bundle | Creates an HPM Part project.| | Creating a project| hpm&nbsp;init&nbsp;bundle | Creates an HPM Part project.|
| hpm&nbsp;init&nbsp;-t&nbsp;template | Creates a scaffolding project from a template.| || hpm&nbsp;init&nbsp;-t&nbsp;template | Creates a scaffolding project from a template.|
| Installing HPM Parts| **hpm install** or **hpm i**| Installs dependent HPM Parts in the bundle.json file.| | Installing HPM Parts| **hpm install** or **hpm i**| Installs dependent HPM Parts in the bundle.json file.|
| hpm&nbsp;install&nbsp;bundle\@version | Installs HPM Parts of a specified version.| || hpm&nbsp;install&nbsp;bundle\@version | Installs HPM Parts of a specified version.|
| Uninstalling HPM Parts| hpm&nbsp;uninstall&nbsp;bundle | Uninstalls dependent HPM Parts.| | Uninstalling HPM Parts| hpm&nbsp;uninstall&nbsp;bundle | Uninstalls dependent HPM Parts.|
| **hpm remove** or **hpm rm bundlename**| Uninstalls dependent HPM Parts.| || **hpm remove** or **hpm rm bundlename**| Uninstalls dependent HPM Parts.|
| Viewing information| **hpm list** or **hpm ls**| Displays the dependency tree of the HPM part.| | Viewing information| **hpm list** or **hpm ls**| Displays the dependency tree of the HPM part.|
| hpm&nbsp;dependencies | Generates the dependency relationship data of the HPM Part. (This command is also integrated in the **hpm ui** command. After you run the hpm ui command, a hpm UI is displayed with the dependencies.)| || hpm&nbsp;dependencies | Generates the dependency relationship data of the HPM Part. (This command is also integrated in the **hpm ui** command. After you run the hpm ui command, a hpm UI is displayed with the dependencies.)|
| Searching for HPM Parts| hpm&nbsp;search&nbsp;name | Searches for HPM Parts. **--json** is used to specify the search result in JSON format, and **-type** is used to set the target type, which can be **part**, **distribution**, or **code-segment**.| | Searching for HPM Parts| hpm&nbsp;search&nbsp;name | Searches for HPM Parts. **--json** is used to specify the search result in JSON format, and **-type** is used to set the target type, which can be **part**, **distribution**, or **code-segment**.|
| Setting HPM configuration items| hpm&nbsp;config&nbsp;set&nbsp;key&nbsp;value | Sets configuration items, such as the server address and network proxy.| | Setting HPM configuration items| hpm&nbsp;config&nbsp;set&nbsp;key&nbsp;value | Sets configuration items, such as the server address and network proxy.|
| hpm&nbsp;config&nbsp;delete&nbsp;key | Deletes configurations.| || hpm&nbsp;config&nbsp;delete&nbsp;key | Deletes configurations.|
| Updating HPM Part versions| hpm&nbsp;update | Updates the versions of dependent HPM Parts.| | Updating HPM Part versions| hpm&nbsp;update | Updates the versions of dependent HPM Parts.|
| hpm&nbsp;check-update | Checks whether version updates are available to dependent HPM Parts.| || hpm&nbsp;check-update | Checks whether version updates are available to dependent HPM Parts.|
| Building| hpm&nbsp;build | Builds an HPM Part.| | Building| hpm&nbsp;build | Builds an HPM Part.|
| hpm&nbsp;dist | Builds a distribution. The build depends on the **dist** script in **scripts** of **bundle.json**.| || hpm&nbsp;dist | Builds a distribution. The build depends on the **dist** script in **scripts** of **bundle.json**.|
| Packing | hpm&nbsp;pack | Packs dependencies of local HPM Parts.| | Packing | hpm&nbsp;pack | Packs dependencies of local HPM Parts.|
| Burning| hpm&nbsp;run&nbsp;flash | Burns the firmware. The firmware burning depends on the **flash** script in **scripts** of **bundle.json**.| | Burning| hpm&nbsp;run&nbsp;flash | Burns the firmware. The firmware burning depends on the **flash** script in **scripts** of **bundle.json**.|
| Publishing| hpm&nbsp;publish | Publishes an HPM Part, which must be unique in the repository and has a unique version. (An account is required for login.)| | Publishing| hpm&nbsp;publish | Publishes an HPM Part, which must be unique in the repository and has a unique version. (An account is required for login.)|
...@@ -242,7 +242,7 @@ HPM Part dependencies (including indirect dependencies) can be displayed by runn ...@@ -242,7 +242,7 @@ HPM Part dependencies (including indirect dependencies) can be displayed by runn
``` ```
$ hpm list $ hpm list
+--demo@1.0.0 +--demo@1.0.0
| +--@huawei/media@1.0.2 | +--@example/media@1.0.2
| +--@demo/sport_hi3518ev300_liteos_a@1.0.0 | +--@demo/sport_hi3518ev300_liteos_a@1.0.0
| | +--@demo/app@4.0.1 | | +--@demo/app@4.0.1
| | | +--@demo/build@4.0.1 | | | +--@demo/build@4.0.1
......
...@@ -172,5 +172,10 @@ ...@@ -172,5 +172,10 @@
- [Kernel for Standard Systems](kernel-standard.md) - [Kernel for Standard Systems](kernel-standard.md)
- [Linux Kernel Overview](kernel-standard-overview.md) - [Linux Kernel Overview](kernel-standard-overview.md)
- [Applying Patches on OpenHarmony Development Boards](kernel-standard-patch.md) - [Applying Patches on Development Boards](kernel-standard-patch.md)
- [Guidelines for Building the Linux Kernel](kernel-standard-build.md) - [Compiling and Building the Linux Kernel](kernel-standard-build.md)
\ No newline at end of file - [Enhanced Kernel Features](kernel-standard-enhanced-features.md)
- [Enhanced SWAP](kernel-standard-mm-eswap.md)
- [Task Scheduling](kernel-standard-sched.md)
- [Related Thread Group](kernel-standard-sched-rtg.md)
- [Lightweight CPU Isolation](kernel-standard-sched-cpuisolation.md)
\ No newline at end of file
# Queue<a name="EN-US_TOPIC_0000001123863117"></a> # Queue<a name="EN-US_TOPIC_0000001123863117"></a>
- [Basic Concepts](#section5747112216469)
- [Working Principles](#section1582619446311)
- [Queue Control Block](#section1648304614720)
- [Working Principles](#section15384012164811)
- [Available APIs](#section158501652121514)
- [How to Develop](#section783435801510)
- [Development Example](#section460018317164)
- [Example Description](#section2148236125814)
- [Sample Code](#section121451047155716)
- [Verification](#section2742182082117)
## Basic Concepts<a name="section5747112216469"></a> ## Basic Concepts<a name="section5747112216469"></a>
...@@ -19,7 +8,7 @@ A queue, also called a message queue, is a data structure used for communication ...@@ -19,7 +8,7 @@ A queue, also called a message queue, is a data structure used for communication
Tasks can read messages from a queue. When the queue has no messages, the tasks are suspended. When the queue has a new message, the suspended tasks are woken up and process the new message. Tasks can also write messages to the queue. When the queue is full, the write task is suspended. When there is an available message node in the queue, the suspended write task is woken up and writes a message. Tasks can read messages from a queue. When the queue has no messages, the tasks are suspended. When the queue has a new message, the suspended tasks are woken up and process the new message. Tasks can also write messages to the queue. When the queue is full, the write task is suspended. When there is an available message node in the queue, the suspended write task is woken up and writes a message.
You can adjust the timeout period of the read queue and write queue to adjust the block mode of the read and write APIs. If the timeout period is set to **0** for the read queue and write queue, tasks will not be suspended and the API directly returns. This is the non-block mode. If the timeout period is greater than **0**, block mode is used. You can adjust the timeout period of the read queue and write queue to adjust the block mode of the read and write APIs. If the timeout period is set to **0** for the read queue and write queue, tasks will not be suspended and the API directly returns. This is the non-block mode. If the timeout period is greater than **0**, block mode is used.
An asynchronous processing mechanism is provided to allow messages in a queue not to be processed immediately. In addition, queues can be used to buffer messages and implement asynchronous task communication. Queues have the following features: An asynchronous processing mechanism is provided to allow messages in a queue not to be processed immediately. In addition, queues can be used to buffer messages and implement asynchronous task communication. Queues have the following features:
...@@ -64,12 +53,12 @@ Each queue control block contains information about the queue status. ...@@ -64,12 +53,12 @@ Each queue control block contains information about the queue status.
### Working Principles<a name="section15384012164811"></a> ### Working Principles<a name="section15384012164811"></a>
- The queue ID is returned if a queue is created successfully. - The queue ID is returned if a queue is created successfully.
- The queue control block contains **Head** and **Tail**, which indicate the storage status of messages in a queue. **Head** indicates the start position of occupied message nodes in the queue. **Tail** indicates the end position of the occupied message nodes and the start position of idle message nodes. When a queue is created, **Head** and **Tail** point to the start position of the queue. - The queue control block contains **Head** and **Tail**, which indicate the storage status of messages in a queue. **Head** indicates the start position of occupied message nodes in the queue. **Tail** indicates the end position of the occupied message nodes and the start position of idle message nodes. When a queue is created, **Head** and **Tail** point to the start position of the queue.
- When data is to be written to a queue, **readWriteableCnt\[1\]** is used to determine whether data can be written to the queue. If **readWriteableCnt\[1\]** is **0**, the queue is full and data cannot be written to it. Data can be written to the head node or tail node of a queue. To write data to the tail node, locate the start idle message node based on **Tail** and write data to it. If **Tail** is pointing to the tail of the queue, the rewind mode is used. To write data to the head node, locate previous node based on **Head** and write data to it. If **Head** is pointing to the start position of the queue, the rewind mode is used. - When data is to be written to a queue, **readWriteableCnt\[1\]** is used to determine whether data can be written to the queue. If **readWriteableCnt\[1\]** is **0**, the queue is full and data cannot be written to it. Data can be written to the head node or tail node of a queue. To write data to the tail node, locate the start idle message node based on **Tail** and write data to it. If **Tail** is pointing to the tail of the queue, the rewind mode is used. To write data to the head node, locate previous node based on **Head** and write data to it. If **Head** is pointing to the start position of the queue, the rewind mode is used.
- When a queue is to be read, **readWriteableCnt\[0\]** is used to determine whether the queue has messages to read. Reading an idle queue \(**readWriteableCnt\[0\]** is** 0**\) will cause task suspension. If the queue has messages to read, the system locates the first node to which data is written based on **Head** and read the message from the node. If **Head** is pointing to the tail of the queue, the rewind mode is used. - When a queue is to be read, **readWriteableCnt\[0\]** is used to determine whether the queue has messages to read. Reading an idle queue \(**readWriteableCnt\[0\]** is **0**\) will cause task suspension. If the queue has messages to read, the system locates the first node to which data is written based on **Head** and read the message from the node. If **Head** is pointing to the tail of the queue, the rewind mode is used.
- When a queue is to be deleted, the system locates the queue based on the queue ID, sets the queue status to **OS\_QUEUE\_UNUSED**, sets the queue control block to the initial state, and releases the memory occupied by the queue. - When a queue is to be deleted, the system locates the queue based on the queue ID, sets the queue status to **OS\_QUEUE\_UNUSED**, sets the queue control block to the initial state, and releases the memory occupied by the queue.
**Figure 1** Reading and writing data in a queue<a name="fig1343517592468"></a> **Figure 1** Reading and writing data in a queue<a name="fig1343517592468"></a>
![](figures/reading-and-writing-data-in-a-queue.png "reading-and-writing-data-in-a-queue") ![](figures/reading-and-writing-data-in-a-queue.png "reading-and-writing-data-in-a-queue")
The preceding figure illustrates how to write data to the tail node only. Writing data to the head node is similar. The preceding figure illustrates how to write data to the tail node only. Writing data to the head node is similar.
...@@ -143,20 +132,20 @@ The preceding figure illustrates how to write data to the tail node only. Writin ...@@ -143,20 +132,20 @@ The preceding figure illustrates how to write data to the tail node only. Writin
## How to Develop<a name="section783435801510"></a> ## How to Develop<a name="section783435801510"></a>
1. Call **LOS\_QueueCreate** to create a queue. The queue ID is returned when the queue is created. 1. Call **LOS\_QueueCreate** to create a queue. The queue ID is returned when the queue is created.
2. Call **LOS\_QueueWrite** or **LOS\_QueueWriteCopy** to write messages to the queue. 2. Call **LOS\_QueueWrite** or **LOS\_QueueWriteCopy** to write messages to the queue.
3. Call **LOS\_QueueRead** or **LOS\_QueueReadCopy** to read messages from the queue. 3. Call **LOS\_QueueRead** or **LOS\_QueueReadCopy** to read messages from the queue.
4. Call **LOS\_QueueInfoGet** to obtain queue information. 4. Call **LOS\_QueueInfoGet** to obtain queue information.
5. Call **LOS\_QueueDelete** to delete the queue. 5. Call **LOS\_QueueDelete** to delete the queue.
>![](../public_sys-resources/icon-note.gif) **NOTE:** >![](../public_sys-resources/icon-note.gif) **NOTE:**
>- The maximum number of queues supported by the system is the total number of queue resources of the system, not the number of queue resources available to users. For example, if the system software timer occupies one more queue resource, the number of queue resources available to users decreases by one. >- The maximum number of queues supported by the system is the total number of queue resources of the system, not the number of queue resources available to users. For example, if the system software timer occupies one more queue resource, the number of queue resources available to users decreases by one.
>- The input parameters queue name and flags passed when a queue is created are reserved for future use. >- The input parameters queue name and flags passed when a queue is created are reserved for future use.
>- The input parameter **timeOut** in the queue interface function is relative time. >- The input parameter **timeOut** in the queue interface function is relative time.
>- **LOS\_QueueReadCopy**, **LOS\_QueueWriteCopy**, and **LOS\_QueueWriteHeadCopy** are a group of APIs that must be used together. **LOS\_QueueRead**, **LOS\_QueueWrite**, and **LOS\_QueueWriteHead** are a group of APIs that must be used together. >- **LOS\_QueueReadCopy**, **LOS\_QueueWriteCopy**, and **LOS\_QueueWriteHeadCopy** are a group of APIs that must be used together. **LOS\_QueueRead**, **LOS\_QueueWrite**, and **LOS\_QueueWriteHead** are a group of APIs that must be used together.
>- As **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are used to manage data addresses, you must ensure that the memory directed by the pointer obtained by calling **LOS\_QueueRead** is not modified or released abnormally when the queue is being read. Otherwise, unpredictable results may occur. >- As **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are used to manage data addresses, you must ensure that the memory directed by the pointer obtained by calling **LOS\_QueueRead** is not modified or released abnormally when the queue is being read. Otherwise, unpredictable results may occur.
>- If the input parameter bufferSize in **LOS\_QueueReadCopy** is less than the actual length of the message, the message will be truncated. >- If the input parameter **bufferSize** in **LOS\_QueueReadCopy** is less than the length of the message, the message will be truncated.
>- **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are called to manage data addresses, which means that the actual data read or written is pointer data. Therefore, before using these APIs, ensure that the message node size is the pointer length during queue creation, to avoid waste and read failures. >- **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are called to manage data addresses, which means that the actual data read or written is pointer data. Therefore, before using these APIs, ensure that the message node size is the pointer length during queue creation, to avoid waste and read failures.
## Development Example<a name="section460018317164"></a> ## Development Example<a name="section460018317164"></a>
...@@ -164,11 +153,11 @@ The preceding figure illustrates how to write data to the tail node only. Writin ...@@ -164,11 +153,11 @@ The preceding figure illustrates how to write data to the tail node only. Writin
Create a queue and two tasks. Enable task 1 to call the queue write API to send messages, and enable task 2 to receive messages by calling the queue read API. Create a queue and two tasks. Enable task 1 to call the queue write API to send messages, and enable task 2 to receive messages by calling the queue read API.
1. Create task 1 and task 2 by calling **LOS\_TaskCreate**. 1. Create task 1 and task 2 by calling **LOS\_TaskCreate**.
2. Create a message queue by calling **LOS\_QueueCreate**. 2. Create a message queue by calling **LOS\_QueueCreate**.
3. Enable messages to be sent in task 1 by calling **SendEntry**. 3. Enable messages to be sent in task 1 by calling **SendEntry**.
4. Enable messages to be received in task 2 by calling **RecvEntry**. 4. Enable messages to be received in task 2 by calling **RecvEntry**.
5. Call **LOS\_QueueDelete** to delete the queue. 5. Call **LOS\_QueueDelete** to delete the queue.
### Sample Code<a name="section121451047155716"></a> ### Sample Code<a name="section121451047155716"></a>
......
# Queue<a name="EN-US_TOPIC_0000001078912736"></a> # Queue<a name="EN-US_TOPIC_0000001078912736"></a>
- [Basic Concepts](#section81171363232)
- [Working Principles](#section1074515132316)
- [Queue Control Block](#section194431851201315)
- [Working Principles](#section89875741418)
- [Development Guidelines](#section827981242419)
- [Available APIs](#section19327151642413)
- [How to Develop](#section1390154210243)
- [Development Example](#section27132341285)
- [Example Description](#section197311443141017)
- [Sample Code](#section972214490107)
- [Verification](#section19287165416106)
## Basic Concepts<a name="section81171363232"></a> ## Basic Concepts<a name="section81171363232"></a>
...@@ -21,7 +7,7 @@ A queue, also called a message queue, is a data structure used for communication ...@@ -21,7 +7,7 @@ A queue, also called a message queue, is a data structure used for communication
Tasks can read messages from a queue. When the queue has no messages, the tasks are suspended. When the queue has a new message, the suspended tasks are woken up and process the new message. Tasks can also write messages to the queue. When the queue is full, the write task is suspended. When there is an available message node in the queue, the suspended write task is woken up and writes a message. Tasks can read messages from a queue. When the queue has no messages, the tasks are suspended. When the queue has a new message, the suspended tasks are woken up and process the new message. Tasks can also write messages to the queue. When the queue is full, the write task is suspended. When there is an available message node in the queue, the suspended write task is woken up and writes a message.
You can adjust the timeout period of the read queue and write queue to adjust the block mode of the read and write APIs. If the timeout period is set to **0** for the read queue and write queue, tasks will not be suspended and the API directly returns. This is the non-block mode. If the timeout period is greater than **0**, block mode is used. You can adjust the timeout period of the read queue and write queue to adjust the block mode of the read and write APIs. If the timeout period is set to **0** for the read queue and write queue, tasks will not be suspended and the API directly returns. This is the non-block mode. If the timeout period is greater than **0**, block mode is used.
An asynchronous processing mechanism is provided to allow messages in a queue not to be processed immediately. In addition, queues can be used to buffer messages and implement asynchronous task communication. Queues have the following features: An asynchronous processing mechanism is provided to allow messages in a queue not to be processed immediately. In addition, queues can be used to buffer messages and implement asynchronous task communication. Queues have the following features:
...@@ -63,12 +49,12 @@ Each queue control block contains information about the queue status. ...@@ -63,12 +49,12 @@ Each queue control block contains information about the queue status.
### Working Principles<a name="section89875741418"></a> ### Working Principles<a name="section89875741418"></a>
- The queue ID is returned if a queue is created successfully. - The queue ID is returned if a queue is created successfully.
- The queue control block contains **Head** and **Tail**, which indicate the storage status of messages in a queue. **Head** indicates the start position of occupied message nodes in the queue. **Tail** indicates the end position of the occupied message nodes and the start position of idle message nodes. When a queue is created, **Head** and **Tail** point to the start position of the queue. - The queue control block contains **Head** and **Tail**, which indicate the storage status of messages in a queue. **Head** indicates the start position of occupied message nodes in the queue. **Tail** indicates the end position of the occupied message nodes and the start position of idle message nodes. When a queue is created, **Head** and **Tail** point to the start position of the queue.
- When data is to be written to a queue, **readWriteableCnt\[1\]** is used to determine whether data can be written to the queue. If **readWriteableCnt\[1\]** is **0**, the queue is full and data cannot be written to it. Data can be written to the head node or tail node of a queue. To write data to the tail node, locate the start idle message node based on **Tail** and write data to it. If **Tail** is pointing to the tail of the queue, the rewind mode is used. To write data to the head node, locate previous node based on **Head** and write data to it. If **Head** is pointing to the start position of the queue, the rewind mode is used. - When data is to be written to a queue, **readWriteableCnt\[1\]** is used to determine whether data can be written to the queue. If **readWriteableCnt\[1\]** is **0**, the queue is full and data cannot be written to it. Data can be written to the head node or tail node of a queue. To write data to the tail node, locate the start idle message node based on **Tail** and write data to it. If **Tail** is pointing to the tail of the queue, the rewind mode is used. To write data to the head node, locate previous node based on **Head** and write data to it. If **Head** is pointing to the start position of the queue, the rewind mode is used.
- When a queue is to be read, **readWriteableCnt\[0\]** is used to determine whether the queue has messages to read. Reading an idle queue \(**readWriteableCnt\[0\]** is** 0**\) will cause task suspension. If the queue has messages to read, the system locates the first node to which data is written based on **Head** and read the message from the node. If **Head** is pointing to the tail of the queue, the rewind mode is used. - When a queue is to be read, **readWriteableCnt\[0\]** is used to determine whether the queue has messages to read. Reading an idle queue \(**readWriteableCnt\[0\]** is** 0**\) will cause task suspension. If the queue has messages to read, the system locates the first node to which data is written based on **Head** and read the message from the node. If **Head** is pointing to the tail of the queue, the rewind mode is used.
- When a queue is to be deleted, the system locates the queue based on the queue ID, sets the queue status to **OS\_QUEUE\_UNUSED**, sets the queue control block to the initial state, and releases the memory occupied by the queue. - When a queue is to be deleted, the system locates the queue based on the queue ID, sets the queue status to **OS\_QUEUE\_UNUSED**, sets the queue control block to the initial state, and releases the memory occupied by the queue.
**Figure 1** Reading and writing data in a queue<a name="fig139854471119"></a> **Figure 1** Reading and writing data in a queue<a name="fig139854471119"></a>
![](figures/reading-and-writing-data-in-a-queue-3.png "reading-and-writing-data-in-a-queue-3") ![](figures/reading-and-writing-data-in-a-queue-3.png "reading-and-writing-data-in-a-queue-3")
The preceding figure illustrates how to write data to the tail node only. Writing data to the head node is similar. The preceding figure illustrates how to write data to the tail node only. Writing data to the head node is similar.
...@@ -144,20 +130,20 @@ The preceding figure illustrates how to write data to the tail node only. Writin ...@@ -144,20 +130,20 @@ The preceding figure illustrates how to write data to the tail node only. Writin
### How to Develop<a name="section1390154210243"></a> ### How to Develop<a name="section1390154210243"></a>
1. Call **LOS\_QueueCreate** to create a queue. The queue ID is returned when the queue is created. 1. Call **LOS\_QueueCreate** to create a queue. The queue ID is returned when the queue is created.
2. Call **LOS\_QueueWrite** or **LOS\_QueueWriteCopy** to write messages to the queue. 2. Call **LOS\_QueueWrite** or **LOS\_QueueWriteCopy** to write messages to the queue.
3. Call **LOS\_QueueRead** or **LOS\_QueueReadCopy** to read messages from the queue. 3. Call **LOS\_QueueRead** or **LOS\_QueueReadCopy** to read messages from the queue.
4. Call **LOS\_QueueInfoGet** to obtain queue information. 4. Call **LOS\_QueueInfoGet** to obtain queue information.
5. Call **LOS\_QueueDelete** to delete a queue. 5. Call **LOS\_QueueDelete** to delete a queue.
>![](../public_sys-resources/icon-note.gif) **NOTE:** >![](../public_sys-resources/icon-note.gif) **NOTE:**
>- The maximum number of queues supported by the system is the total number of queue resources of the system, not the number of queue resources available to users. For example, if the system software timer occupies one more queue resource, the number of queue resources available to users decreases by one. >- The maximum number of queues supported by the system is the total number of queue resources of the system, not the number of queue resources available to users. For example, if the system software timer occupies one more queue resource, the number of queue resources available to users decreases by one.
>- The input parameters queue name and flags passed when a queue is created are reserved for future use. >- The input parameters queue name and flags passed when a queue is created are reserved for future use.
>- The input parameter **timeOut** in the queue interface function is relative time. >- The input parameter **timeOut** in the queue interface function is relative time.
>- **LOS\_QueueReadCopy**, **LOS\_QueueWriteCopy**, and **LOS\_QueueWriteHeadCopy** are a group of APIs that must be used together. **LOS\_QueueRead**, **LOS\_QueueWrite**, and **LOS\_QueueWriteHead** are a group of APIs that must be used together. >- **LOS\_QueueReadCopy**, **LOS\_QueueWriteCopy**, and **LOS\_QueueWriteHeadCopy** are a group of APIs that must be used together. **LOS\_QueueRead**, **LOS\_QueueWrite**, and **LOS\_QueueWriteHead** are a group of APIs that must be used together.
>- As **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are used to manage data addresses, you must ensure that the memory directed by the pointer obtained by calling **LOS\_QueueRead** is not modified or released abnormally when the queue is being read. Otherwise, unpredictable results may occur. >- As **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are used to manage data addresses, you must ensure that the memory directed by the pointer obtained by calling **LOS\_QueueRead** is not modified or released abnormally when the queue is being read. Otherwise, unpredictable results may occur.
>- If the input parameter bufferSize in **LOS\_QueueRead**and**LOS\_QueueReadCopy** is less than the actual length of the message, the message will be truncated. >- If the input parameter **bufferSize** in **LOS\_QueueRead** and **LOS\_QueueReadCopy** is less than the length of the message, the message will be truncated.
>- **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are called to manage data addresses, which means that the actual data read or written is pointer data. Therefore, before using these APIs, ensure that the message node size is the pointer length during queue creation, to avoid waste and read failures. >- **LOS\_QueueWrite**, **LOS\_QueueWriteHead**, and **LOS\_QueueRead** are called to manage data addresses, which means that the actual data read or written is pointer data. Therefore, before using these APIs, ensure that the message node size is the pointer length during queue creation, to avoid waste and read failures.
## Development Example<a name="section27132341285"></a> ## Development Example<a name="section27132341285"></a>
...@@ -165,11 +151,11 @@ The preceding figure illustrates how to write data to the tail node only. Writin ...@@ -165,11 +151,11 @@ The preceding figure illustrates how to write data to the tail node only. Writin
Create a queue and two tasks. Enable task 1 to call the queue write API to send messages, and enable task 2 to receive messages by calling the queue read API. Create a queue and two tasks. Enable task 1 to call the queue write API to send messages, and enable task 2 to receive messages by calling the queue read API.
1. Create task 1 and task 2 by calling **LOS\_TaskCreate**. 1. Create task 1 and task 2 by calling **LOS\_TaskCreate**.
2. Create a message queue by calling **LOS\_QueueCreate**. 2. Create a message queue by calling **LOS\_QueueCreate**.
3. Enable messages to be sent in task 1 by calling **SendEntry**. 3. Enable messages to be sent in task 1 by calling **SendEntry**.
4. Enable messages to be received in task 2 by calling **RecvEntry**. 4. Enable messages to be received in task 2 by calling **RecvEntry**.
5. Call **LOS\_QueueDelete** to delete a queue. 5. Call **LOS\_QueueDelete** to delete a queue.
### Sample Code<a name="section972214490107"></a> ### Sample Code<a name="section972214490107"></a>
......
# Guidelines for Compiling and Building the Linux Kernel<a name="EN-US_TOPIC_0000001076416924"></a> # Compiling and Building the Linux Kernel<a name="EN-US_TOPIC_0000001076416924"></a>
- [Example 1](#section19369206113115) - [Example 1](#section19369206113115)
......
# Enhanced Kernel Features
- **[Memory Management](kernel-standard-mm.md)**
- **[Task Scheduling](kernel-standard-sched.md)**
# Enhanced SWAP
## Basic Concepts
Enhanced Swap (ESwap) allows a custom partition to serve as a swap partition and uses a resident process zswapd to encrypt and swap the anonymous pages compressed by [zram](https://www.kernel.org/doc/html/latest/admin-guide/blockdev/zram.html) to the ESwap partition. In this way, a block of memory can be completely released to ensure the available memory (Memavailable) waterline. In addition to this reclaiming mechanism, the entire memory framework is enhanced to improve the reclaiming efficiency of anonymous pages and file pages and streamline the reclaiming ratio of these two types of pages to prevent refaults caused by excessive reclamation.
## Configuring zram and ESwap
### Enabling ESwap
1. Enable related configuration items and dependencies.
To enable ESwap, you need to enable the corresponding configuration items and dependencies during kernel compilation. The configuration items related to ESwap are as follows:
```
CONFIG_HYPERHOLD=y
CONFIG_HYPERHOLD_DEBUG=y
CONFIG_HYPERHOLD_ZSWAPD=y
CONFIG_HYPERHOLD_FILE_LRU=y
CONFIG_HYPERHOLD_MEMCG=y
CONFIG_ZRAM_GROUP=y
CONFIG_ZRAM_GROUP_DEBUG=y
CONFIG_ZLIST_DEBUG=y
CONFIG_ZRAM_GROUP_WRITEBACK=y
```
Enable the following dependencies:
```
CONFIG_MEMCG=y
CONFIG_SWAP=y
CONFIG_ZSMALLOC=y
CONFIG_ZRAM=y
```
2. Create an ESwap device.
You can use any block device as the ESwap device. In this example, create the **hpdisk** file and mount it to the loop6 device.
```Bash
// Run the dd command to create the hpdisk file for ESwap. In this example, the file size is 512 MB. Set the file size based on service requirements.
dd if=/dev/random of=/data/hpdisk bs=4096 count=131072
// Associate the hpdisk file created with the ESwap device.
losetup /dev/block/loop6 hpdisk
```
3. Configure ESwap.
Bind the device created in 2 as the ESwap device.
```Bash
echo /dev/block/loop6 > /proc/sys/kernel/hyperhold/device
```
By default, ESwap encrypts the data swapped out. If the ESwap device created in step 2 supports inline encryption, you can disable the ESwap software encryption function.
```Bash
// Check whether hardware-based encryption is supported and enabled. If not, do not perform this operation.
echo 0 > /proc/sys/kernel/hyperhold/soft_crypt
```
> ![icon-caution.gif](../public_sys-resources/icon-caution.gif)**CAUTION**<br/>
> For security purposes, all swapped content must be encrypted. If the ESwap device created does not support inline encryption or the inline encryption macro is not enabled during compilation, ESwap cannot be enabled after software encryption is disabled.
4. Enable ESwap.
After ESwap is enabled, the preceding configuration cannot be modified.
```Bash
echo enable > /proc/sys/kernel/hyperhold/enable
```
> ![icon-note.gif](../public_sys-resources/icon-note.gif)**NOTE**<br/>
> Enable ESwap before zram is enabled. If ESwap is not used, you can enable zram only. If a device does not have the storage device for swap-out or have the corresponding storage partition created, you can enable ZRAM to reclaim memory using **zswapd**.
### Enabling zram
1. Initialize zram.
Configure the interaction between zram and ESwap and set the zram size.
```Bash
// Enable the swap-in and swap-out functions from zram to ESwap. Perform this step before setting the zram size.
echo readwrite > /sys/block/zram0/group
// Set the zram size. In this example, the zram size is set to 512 MB.
echo 512M > /sys/block/zram0/disksize
```
> ![icon-note.gif](../public_sys-resources/icon-note.gif)**NOTE**<br/>
> The parameters and functions of **/sys/block/zram0/group** are as follows:
>
> - **disable**: disables the function.
> - **readonly**: only records the cgroup information of the data but not swap it out.
> - **readwrite**: enables swap-in and swap-out from zram to ESwap.
2. Enable zram.
Use the zram device as the swap partition.
```Bash
mkswap /dev/block/zram0
swapon /dev/block/zram0
```
### Disabling ESwap and zram
1. Disable ESwap.
```Bash
echo disable > /proc/sys/kernel/hyperhold/enable
Or
echo force_disable > /proc/sys/kernel/hyperhold/enable
```
> ![icon-note.gif](../public_sys-resources/icon-note.gif)**NOTE**<br/>
> The difference of the two commands is as follows:
>
> - **disable**: If there is no data in the ESwap partition, disable ESwap. Otherwise, changes ESwap to read-only mode.
> - **force_disable**: If there is no data in the ESwap partition, disable ESwap. Otherwise, changes ESwap to read-only mode and disable ESwap until all data in the ESWAP partition is read.
2. Disable zram and zram group.
```Bash
// If swapon is executed, run swapoff first.
swapoff /dev/block/zram0
echo 1 > /sys/block/zram0/reset
```
## ESwap APIs
ESwap provides APIs to control swap-in and swap-out policies and record the current status. These APIs are located in the directory to which memcg is mounted, for example, `/dev/memcg/`.
| Category| API| Description|
| -------- | -------- | -------- |
| Control| [avail_buffers](#avail_buffers) | Sets the buffer range.|
| | [zswapd_single_memcg_param](#zswapd_single_memcg_param) | Sets memcg configuration.|
| | [zram_wm_ratio](#zram_wm_ratio) | Sets the zram swap-out waterline.|
| Status| [zswapd_pressure_show](#zswapd_pressure_show) | Records the current buffer and refault.|
| | [stat](#stat) | Checks the real-time status of ESwap.|
| | [zswapd_vmstat_show](#zswapd_vmstat_show) | Records events during the zswapd running.|
> ![icon-caution.gif](../public_sys-resources/icon-caution.gif)**CAUTION**<br/>
> Only **avail_buffers** proactively wakes up zswapd because the buffer waterline is adjusted. Other control APIs do not proactively wake up zswapd, but their configuration takes effect only after zswapd is woken up.
The APIs are described as follows:
### avail_buffers
The **avail_buffers** API sets the buffer range [min_avail_buffers, high_avail_buffers]. When the current buffer is less than the value of **min_avail_buffers**, zswapd will be woken up to reclaim anonymous pages. The expected amount of memory to reclaim is the difference between the value of **high_avail_buffers** and the current system buffer value. In fact, less memory is reclaimed due to reasons such as reclamation failure.
The parameters include the following:
- **avail_buffers** indicates the expected buffer value.
- **free_swap_threshold** indicates the threshold of the free capacity of the swap partition. After zswapd is woken up to reclaim memory, press events, such as medium press and critical press, will be recorded based on the current system status and the settings of these two parameters.
You can proactively adjust the values to trigger zswapd reclamation.
Example:
`echo 1000 950 1050 0 > /dev/memcg/memory.avail_buffers`
Default value:
```
avail_buffers: 0
min_avail_buffers: 0
high_avail_buffers: 0
free_swap_threshold: 0
```
Limit:
0<=min_avail_buffers<=avail_buffers<=high_avail_buffers
0<=free_swap_threashold
The values are all integers.
### zswapd_single_memcg_param
The **zswapd_single_memcg_param** API sets the memcg configuration. The parameters include the following:
- **score** indicates the current memcg reclamation priority.
- **ub_mem2zram_ratio** indicates the memory compression ratio to zram.
- **ub_zram2ufs_ratio** indicates the ratio of zram to ESwap.
- **refault_threshold** indicates the refault threshold.
You can modify the parameters to control zram compression and ESwap.
Example:
`echo 60 10 50 > memory.zswapd_single_memcg_param`
Default value:
```
memcg score: 300
memcg ub_mem2zram_ratio: 60
memcg ub_zram2ufs_ratio: 10
memcg refault_threshold: 50
```
Limit:
0<=ub_mem2zram_ratio<=100
0<=ub_zram2ufs_ratio<=100
0<=refault_threshold<=100
The values are all integers.
### zram_wm_ratio
The **zram_wm_ratio** API sets the zram swap-out waterline. When the size of the compressed anonymous page in the zram partition is greater than the total size of zram multiplied by **zram_wm_ratio**, the page is swapped out to the ESwap partition. The swap is performed after zswapd is woken up by the buffer waterline. The system defaults the value **0** as **37**. You can change the value as required.
Example:
`echo 30 > /dev/memcg/memory.zram_wm_ratio`
Default value:
```
zram_wm_ratio: 0
```
Limit:
0<=zram_wm_ratio<=100
The value is an integer.
### zswapd_pressure_show
The **zswapd_pressure_show** API records the zswapd status. **buffer_size** indicates the current buffer size of the system, and **recent_refault** indicates the number of refaults occurred.
### stat
In addition to **memcg.stat**, the **stat** API is added with **Anon**, **File**, **zram**, and **Eswap** to monitor ESwap in real time.
### zswapd_vmstat_show
The **zswapd_vmstat_show** API records events occurred during the zswapd running.
## Triggering zswapd
You can check the current buffer value by running `cat /dev/memcg/memory.zswapd_pressure_show`. For example, if the current buffer value is 1200, you can adjust the buffer range to wake up zswapd.
```Bash
echo 1300 1250 1350 0 > /dev/memcg/memory.avail_buffers
```
## ESwap Size
Set zram and ESwap partition sizes based on service requirements and hardware features. For the rk3568 board whose RAM is 2 GB, the zram and ESwap partitions are set to 512 MB.
# Memory Management
- **[Enhanced Swap] (kernel-standard-mm-eswap.md)**
# Guidelines for Using Patches on OpenHarmony Development Boards<a name="EN-US_TOPIC_0000001081980461"></a> # Applying Patches on Development Boards<a name="EN-US_TOPIC_0000001081980461"></a>
1. Apply the HDF patches. 1. Apply the HDF patches.
......
# Lightweight CPU Isolation
## Basic Concepts
Lightweight CPU isolation enables dynamic CPU isolation based on the system load and user configuration. The kernel migrates the tasks and interrupts from the isolated CPU to other CPUs for execution. The isolated CPU enters the idle state, which reduces the power consumption. In addition, user-mode configuration and query APIs are provided for better system optimization.
## Configuration
### Enabling Lightweight CPU Isolation
Enable related configuration items and dependencies.
To enable lightweight CPU isolation, you need to enable the corresponding configuration items and dependencies during kernel compilation. The related configuration items are as follows:
```
CONFIG_CPU_ISOLATION_OPT=y
CONFIG_SCHED_CORE_CTRL=y
```
Enable the following dependencies:
```
CONFIG_SMP=y
CONFIG_SCHED_WALT=y
```
## Available APIs
APIs are provided to set the number of isolated CPU cores and record the current status. Configurations can be performed based on CPU clusters. These APIs are located in the first CPU device directory of each CPU cluster, for example, `/sys/devices/system/cpu/cpu0/core_ctl`.
| Category| API | Description |
| ---- | ------------ | ---------------------------------------- |
| Control API| enable | Enables or disables the lightweight CPU isolation. The value **1** means enable, and **0** means disable. |
| | min_cpus | Sets the minimum number of active (not isolated) CPUs. |
| | max_cpus | Sets the maximum number of active (not isolated) CPUs. The maximum value is the number of CPUs in a CPU cluster.|
| Status API| active_cpus | Obtains the number of active (not isolated) CPUs. |
| | need_cpus | Obtains the number of CPUs to de-isolate. |
| | global_state | Records the status of all CPU clusters in the system, including the CPU isolation status, online status, and load information.|
# Related Thread Group
## Basic Concepts
The Related Thread Group (RTG) provides optimized scheduling of a group of important threads. The load of an RTG can be collected and predicted separately and the preferred CPU cluster can be set to allow the important threads to run on the optimal CPU and the kernel to select a proper CPU frequency based on the group loads.
## Configuration
### Enabling RTG
To enable RTG, you need to enable the related configuration items and dependencies during kernel compilation. The related configuration items are as follows:
```
CONFIG_SCHED_RTG=y
CONFIG_SCHED_RTG_DEBUG=y
CONFIG_SCHED_RTG_FRAME=y
CONFIG_SCHED_RTG_RT_THREAD_LIMIT=y
```
Enable the following dependencies:
```
CONFIG_SCHED_WALT=y
```
### Adding a Process or Thread to an RTG
By default, 20 RTGs are created in the kernel. The group with ID of 1 is reserved and cannot be added with any process or thread.
```Bash
// Add a process to an RTG.
echo 2 > /proc/<pid>/sched_group_id
// Remove a process from an RTG. The group with ID of 0 is not an RTG.
echo 0 > /proc/<pid>/sched_group_id
```
### Obtaining RTG Information
The RTG information includes group ID, preferred CPU cluster ID, and thread information.
```Bash
cat /proc/sched_rtg_debug
// The following information is displayed:
RTG_ID : 2 // RTG ID.
RTG_INTERVAL : UPDATE:8ms\#INVALID:4294ms // CPU frequency modulation interval and valid load duration.
RTG_CLUSTER : -1 // CPU cluster ID. The value **-1** means that the preferred cluster is not set.
RTG_THREADS: 0/1 // Total number of threads in the group.
STATE COMM PID PRIO CPU // Thread information, including the status, name, PID, priority, and CPU ID.
---------------------------------------------------------
S bash 436 120 1(0-3)
```
## Available APIs
The RTG provides the device node and ioctl APIs for querying and configuring group information. The device node is in `/dev/sched_rtg_ctrl`.
| Device Node | request | Description |
| ------------------- | ------------------- | ------------------- |
| /dev/sched_rtg_ctrl | CMD_ID_SET_RTG | Creates an RTG, and adds, updates, or deletes threads in the group. |
| | CMD_ID_SET_CONFIG | Configures global group attributes, for example, the maximum number of real-time RTGs.|
| | CMD_ID_SET_RTG_ATTR | Configures specified group attributes, for example, the thread priority. |
| | CMD_ID_SET_MIN_UTIL | Sets the minimum utilization of an RTG. |
# Task Scheduling
- **[Related Thread Group](kernel-standard-sched-rtg.md)**
- **[Lightweight CPU Isolation](kernel-standard-sched-cpuisolation.md)**
# Kernel for Standard Systems # Kernel for Standard Systems
- **[Linux Kernel Overview](kernel-standard-overview.md)**
- **[Guidelines for Using Patches on OpenHarmony Development Boards](kernel-standard-patch.md)** - **[Linux Kernel Overview](kernel-standard-overview.md)**
- **[Guidelines for Compiling and Building the Linux Kernel](kernel-standard-build.md)** - **[Applying Patches on Development Boards](kernel-standard-patch.md)**
- **[Compiling and Building the Linux Kernel](kernel-standard-build.md)**
- **[Enhanced Kernel Features] (kernel-standard-enhanced-features.md)**
...@@ -56,4 +56,11 @@ The download steps for other resources are the same as those in the mainline ver ...@@ -56,4 +56,11 @@ The download steps for other resources are the same as those in the mainline ver
- [Third-Party Library Porting Guide for Mini and Small Systems](porting-thirdparty.md) - [Third-Party Library Porting Guide for Mini and Small Systems](porting-thirdparty.md)
- [Overview](porting-thirdparty-overview.md) - [Overview](porting-thirdparty-overview.md)
- [Porting a Library Built Using CMake](porting-thirdparty-cmake.md) - [Porting a Library Built Using CMake](porting-thirdparty-cmake.md)
- [Porting a Library Built Using Makefile](porting-thirdparty-makefile.md) - [Porting a Library Built Using Makefile](porting-thirdparty-makefile.md)
\ No newline at end of file
## SoC Porting Cases
- [Mini System SoC Porting Cases](porting-minichip-cases.md)
- [Mini-System Devices with Screens — Bestechnic SoC Porting Case](porting-bes2600w-on-minisystem-display-demo.md)
- [Combo Solution – ASR Chip Porting Case](porting-asr582x-combo-demo.md)
# Combo Solution – ASR Chip Porting Case
The IoT combo solution (Wi-Fi+BLE) is developed based on the OpenHarmony LiteOS-M kernel. This document exemplifies how to port code of the DEV.WIFI.A development board powered by the ASR582X chip.
## Compilation and Porting
### Directory Planning
In the directory structure of this solution, the board vendor code is decoupled from the SoC vendor code.
```
device
├── board --- Board vendor directory
│ └── lango --- Board vendor: Lango
│ └── dev_wifi_a --- Board name: DEV.WIFI.A
└── soc --- SoC vendor directory
└── asrmicro --- SoC vendor: ASR
└── asr582x --- SoC series: ASR582X
```
The planned product demo directory is as follows:
```
vendor
└── asrmicro --- Vendor of the product demo.
├── wifi_demo --- Product demo name.
└── xts_demo --- Product name.
```
### Product Definition
The following uses `vendor/asrmicro/wifi_demo` as an example to describe the kernel, board, and subsystem used by the product. The kernel, board model, and board vendor need to be planned in advance, which are involved in the precompilation instruction (`hb set`). The information entered here corresponds to the planned directory. Example:
```
{
"product_name": "wifi_demo", --- Product name.
"type": "mini", --- System type: mini.
"version": "3.0", --- System version: 3.0
"device_company": "lango", --- Board vendor: Lango.
"board": "dev_wifi_a", --- Board name: dev_wifi_a.
"kernel_type": "liteos_m", --- Kernel type: liteos_m.
"kernel_version": "3.0.0", --- Kernel version: 3.0.0.
"subsystems": [] --- Subsystem.
}
```
**device_company** and **board** are used to associate the **//device/board/<device_company>/<board> directory**.
### Board Configuration
In this example, the `device/board/lango/dev_wifi_a` directory is used. Place the **config.gni** file in the **liteos_m** directory. This configuration file is used to describe the board information, including the CPU, toolchain, kernel, and compile flags. Sample code:
```
# Kernel type
kernel_type = "liteos_m"
# Kernel version
kernel_version = "3.0.0"
# Board CPU Type
board_cpu = "cortex-m4"
# Toolchain. Here, arm-none-eabi is used.
board_toolchain = "arm-none-eabi"
# Toolchain path. You can use the system path by entering "", or a custom path.
board_toolchain_path = rebase_path("//device/soc/asrmicro/gcc/gcc-arm-none-eabi/Linux64/bin")
# Board-specific compilation parameters
board_cflags = []
# Board-specific link parameters
board_ld_flags = []
# Board-specific header file
board_include_dirs = []
```
### Precompiling
After the product directory, product definition, and board settings are correctly configured, run the precompilation command `hb set` in the project root directory. Then you can find the related product in the displayed list.
![ohos_config.json](figures/asr582x_ohos_config.png)
After selecting a product, press **Enter**. The `ohos_config.json` file is automatically generated in the root directory. Information about the product to be compiled is listed here.
## Kernel Porting
### Kconfig Adaptation
During the compilation of `//kernel/liteos_m`, you need to use the `Kconfig` file for indexing in the corresponding board and SoC directory.
`Kconfig` in the board directory, for example, `//device/board/lango`:
```
├── dev_wifi_a --- dev_wifi_a board configuration
│ ├── Kconfig.liteos_m.board --- Board configuration options
│ ├── Kconfig.liteos_m.defconfig.board --- Default configuration of the board
│   └── liteos_m
│ └── config.gni --- Board configuration file
├── Kconfig.liteos_m.boards --- Boards configuration of the board vendor
└── Kconfig.liteos_m.defconfig.boards --- Default boards configuration of the board vendor
```
In `dev_wifi_a/Kconfig.liteos_m.board`, **BOARD_DEV_WIFI_A** can be selected only when **SOC_ASR5822S** is selected.
```
config BOARD_DEV_WIFI_A
bool "select board DEV_WIFI_A"
depends on SOC_ASR5822S
```
`Kconfig` in the SoC directory, for example, `//device/soc/asrmicro`:
```
├── asr582x --- ASR582X series
│ ├── Kconfig.liteos_m.defconfig.asr5822s --- Default configuration of the ASR5822S chip
│ ├── Kconfig.liteos_m.defconfig.series --- Default configuration of the ASR582X series
│ ├── Kconfig.liteos_m.series --- Configuration of the ASR582X series
│ └── Kconfig.liteos_m.soc --- ASR582X chip configuration
├── Kconfig.liteos_m.defconfig --- SoC default configuration
├── Kconfig.liteos_m.series --- Series configuration
└── Kconfig.liteos_m.soc --- SoC configuration
```
In **asr582x/Kconfig.liteos_m.series**:
```
config SOC_SERIES_ASR582X
bool "ASR582X Series"
select ARM
select SOC_COMPANY_ASRMICRO --- Select SOC_COMPANY_ASRMICRO.
select CPU_CORTEX_M4
help
Enable support for ASR582X series
```
**SOC_ASR5822S** can be selected in **asr582x/Kconfig.liteos_m.soc** only when **SOC_SERIES_ASR582X** is selected.
```
choice
prompt "ASR582X series SoC"
depends on SOC_SERIES_ASR582X
config SOC_ASR5822S --- Select SOC_ASR5822S.
bool "SoC ASR5822S"
endchoice
```
To compile the board BOARD_DEV_WIFI_A, you need to select **SOC_COMPANY_ASRMICRO**, **SOC_SERIES_ASR582X**, and **SOC_ASR5822S**. You can do so by running `make menuconfig` in `kernel/liteos_m`.
![asr5822s_select.json](figures/asr5822s_select.png)
The configurations are saved in `//vendor/asrmicro/wifi_demo/kernel_configs/debug.config` by default. You can directly modify the configurations in **debug.config**.
```
LOSCFG_BOARD_DEV_WIFI_A=y
LOSCFG_SOC_COMPANY_ASRMICRO=y
LOSCFG_SOC_SERIES_ASR582X=y
LOSCFG_SOC_ASR5822S=y
```
### Modular Compilation
The compilation of `Board` and `SoC` adopts the modular compilation method, starting from `kernel/liteos_m/BUILD.gn` and increasing by level. The adaptation process of this solution is as follows:
1. Create the **BUILD.gn** file in `//device/board/lango` and add the following content to the file:
```
if (ohos_kernel_type == "liteos_m") {
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
module_group(module_name) {
modules = [
"dev_wifi_a", --- Board module
"hcs", --- Module corresponding to the hcs file
]
}
}
```
In the preceding **BUILD.gn** file, **dev_wifi_a** and **hcs** are the module names organized by directory level.
2. In `//device/soc/asrmicro`, use the same method to create the **BUILD.gn** file and add the following content to the file:
```
if (ohos_kernel_type == "liteos_m") {
import("//kernel/liteos_m/liteos.gni")
module_name = get_path_info(rebase_path("."), "name")
module_group(module_name) {
modules = [
"asr582x",
]
}
}
```
3. In the `//device/soc/asrmicro` module at each level, add the **BUILD.gn** file and compile the module. The following uses `//device/soc/asrmicro/asr582x/liteos_m/sdk/startup/BUILD.gn` as an example:
```
import("//kernel/liteos_m/liteos.gni")
config("public") {
include_dirs = [ "." ] --- Common header file
}
kernel_module("asr_startup") { --- Module for compilation
sources = [ --- Source file for compilation
"startup.c",
"board.c",
"startup_cm4.S",
]
include_dirs = [ --- Header files used in the include
"...",
]
}
```
4. To organize links and some compilation options, the following parameters are set in **config("public")** in `//device/soc/asrmicro/asr582x/liteos_m/sdk/config/BUILD.gn`:
```
config("public") {
include_dirs = [] --- Common header file
ldflags = [] --- Link parameters, including the ld file
libs = [] --- Link library
defines = [] --- Definition
```
![](../public_sys-resources/icon-note.gif) **NOTE**
It is recommended that common parameter options and header files not be repeatedly filled in all components.
5. To organize some product applications, this solution adds **list** to the **config.json** file of the vendor. The following uses `//vendor/asrmicro/wifi_demo/config.json` as an example to describe how to add **list** to the **config.json** file:
```
"tests_list": [ --- demo list
{
"enable": "true", --- list switch
"test_modules": [
"example", --- OS basic demo
"wifi_test" --- Wi-Fi demo
]
}
]
```
The demo is managed as a module. To enable or disable a demo, add or delete items in **tests_list**.**tests_list** can be directly read in GN. You need to add the following content to `//device/board/lango/dev_wifi_a/liteos_m/config.gni`:
```
product_conf = read_file("${product_path}/config.json", "json")
product_name = product_conf.product_name
tests_list = product_conf.tests_list
```
After reading the **list**, you can add related component libraries to the corresponding link options. Add the following content to `//device/soc/asrmicro/asr582x/liteos_m/sdk/config/BUILD.gn`:
```
foreach(test_item, tests_list) {
test_enable = test_item.enable
if(test_enable == "true")
{
foreach(test_module, test_item.test_modules) {
ldflags += [ "-l${test_module}" ]
}
}
}
```
### C Library Adaptation
To ensure that the entire system does not distinguish the user mode and kernel mode, the upper-layer components and kernel share the same musl-based C library. This solution uses the musl C library. For details about the third-party library, see `//third_party/musl/porting/liteos_m/kernel/BUILD.gn`.
In addition, the kernel modifies and adapts the code for malloc. For details about the adaptation file, see `//kernel/liteos_m/kal/libc/musl/porting/src/malloc.c`.
In this solution, printf-related APIs are implemented using open-source code. For details about the adaptation file, see `//device/soc/asrmicro/asr582x/liteos_m/sdk/drivers/platform/system/printf-stdarg.c`.
The **wrap** links of the printf-related APIs need to be added to the `//device/board/lango/dev_wifi_a/liteos_m/config.gni` file so that these APIs can be invoked.
```
board_ld_flags += [
"-Wl,--wrap=printf",
"-Wl,--wrap=sprintf",
"-Wl,--wrap=snprintf",
"-Wl,--wrap=vprintf",
"-Wl,--wrap=vsprintf",
"-Wl,--wrap=vsnprintf",
]
```
### Shell Adaptation
To facilitate debugging, this solution integrates the shell component of the kernel. You can select **Enable Shell** in **Debug** of **make menuconfig** or enter **LOSCFG_SHELL=y** in the `//vendor/asrmicro/wifi_demo/kernel_configs/debug.config` file.
The shell component needs to be initialized. For details, see `device/soc/asrmicro/asr582x/liteos_m/sdk/startup/board.c`.
```
ret = LosShellInit();
if (ret != LOS_OK) {
printf("LosShellInit failed! ERROR: 0x%x\n", ret);
}
ret = OsShellInit();
if (ret != LOS_OK) {
printf("OsShellInit failed! ERROR: 0x%x\n", ret);
}
```
After initialization, each shell command needs to be registered, for example, `vendor/asrmicro/wifi_demo/tests/wifi/wifi_app.c`:
```
osCmdReg(CMD_TYPE_STD, "wifi_open", 0, (CMD_CBK_FUNC)ap_conn_func); --- Connect to the AP. Input parameters can be carried.
osCmdReg(CMD_TYPE_EX, "wifi_close", 0, (CMD_CBK_FUNC)ap_close_func); --- Disconnect from the AP.
```
### Kernel Boot Adaptation
After the board enters the **main** function, it is initialized. After that, interrupts are registered, and then the kernel is initialized and scheduled.
For details about interrupt registration, see `//device/soc/asrmicro/asr582x/liteos_m/sdk/startup/board.c`.
```
ArchHwiCreate(UART1_IRQn,configLIBRARY_NORMAL_INTERRUPT_PRIORITY,0,UART1_IRQHandler,0); --- UART interrupt
ArchHwiCreate(GPIO_IRQn,configLIBRARY_NORMAL_INTERRUPT_PRIORITY,0,GPIO_IRQHandler,0); --- GPIO interrupt
```
The following is an example of kernel initialization:
```
osStatus_t ret = osKernelInitialize(); --- Kernel initialization
if(ret == osOK)
{
threadId = osThreadNew((osThreadFunc_t)sys_init,NULL,&g_main_task); --- Create the init thread.
if(threadId!=NULL)
{
osKernelStart(); --- Thread scheduling
}
}
```
In `sys_init`, you need to initialize the Openharmony system components.
```
...
DeviceManagerStart(); --- Initialize HDF.
OHOS_SystemInit(); --- Initialize Openharmony system components.
....
```
### HDF Framework Adaptation
HDF provides a set of unified APIs for applications to access hardware, simplifying application development. To add the HDF component, you need to add it to `//vendor/asrmicro/wifi_demo/kernel_configs/debug.config`:
```
LOSCFG_DRIVERS_HDF=y
LOSCFG_DRIVERS_HDF_PLATFORM=y
```
In addition, you need to add the hardware configuration description file of the corresponding development board to `board`. The file is stored in `//device/board/lango/hcs`. This example takes the GPIO and UART as an example. The porting process is as follows:
#### GPIO Adaptation
1. The chip driver adaptation file is stored in the `//drivers/adapter/platform` directory. Add the `gpio_asr.c` and `gpio_asr.h` files to the `gpio` directory, and add the compilation conditions of the new driver file to `BUILD.gn`.
```
if (defined(LOSCFG_SOC_COMPANY_ASRMICRO)) {
sources += [ "gpio_asr.c" ]
}
```
2. The driver description file in `gpio_asr.c` is as follows:
```
struct HdfDriverEntry g_GpioDriverEntry = {
.moduleVersion = 1,
.moduleName = "ASR_GPIO_MODULE_HDF",
.Init = GpioDriverInit,
.Release = GpioDriverRelease,
};
HDF_INIT(g_GpioDriverEntry);
```
3. Add the GPIO hardware description file `gpio.hcs` to `//device/board/lango/hcs`. The mapped GPIO0 controls the programmable LED on the board. GPIO1 corresponds to the user key. The HCS content is as follows:
```
root {
platform {
gpio_config {
match_attr = "gpio_config";
pin = [0, 1];
// led3: GPIO9
// user key: GPIO7
realPin = [9, 7];
config = [5, 1];
pinNum = 2;
}
}
}
```
4. The configuration information of `gpio.hcs` is loaded in GpioDriverInit, and the corresponding GPIO pins are initialized. The application layer needs only the following simple code to control LED indicators and read key information:
```
int32_t GpioKeyIrqFunc(uint16_t gpio, void *data)
{
printf("user key %d pressed\n", gpio);
}
GpioSetIrq(1, OSAL_IRQF_TRIGGER_FALLING, GpioKeyIrqFunc, NULL);
GpioWrite(0, 0);
lega_rtos_delay_milliseconds(1000);
GpioWrite(0, 1);
```
#### UART Adaptation
1. The chip driver adaptation file is stored in the `//drivers/adapter/platform` directory. Add the `uart_asr.c` and `uart_asr.h` files to the `uart` directory, and add the compilation conditions of the new driver file to `BUILD.gn`.
```
if (defined(LOSCFG_SOC_COMPANY_ASRMICRO)) {
sources += [ "uart_asr.c" ]
}
```
2. The driver description file in `uart_asr.c` is as follows:
```
struct HdfDriverEntry g_hdfUartDevice = {
.moduleVersion = 1,
.moduleName = "HDF_PLATFORM_UART",
.Bind = HdfUartDeviceBind,
.Init = HdfUartDeviceInit,
.Release = HdfUartDeviceRelease,
};
HDF_INIT(g_hdfUartDevice);
```
3. Add the GPIO hardware description file `uart.hcs` to `//device/board/lango/hcs`. The HCS content is as follows:
```
controller_uart0 :: uart_controller {
match_attr = "asr582x_uart_0";
port = 0; /* UART_ID_0 */
pin_tx_pin = 0; /* IO_PIN_10 */
pin_tx_mux = 25; /* IO_MUX_2 */
pin_rx_pin = 1; /* IO_PIN_11 */
pin_rx_mux = 25; /* IO_MUX_2 */
tx_rx = 3; /* TX_RX MODE */
}
```
4. The configuration information of `gpio.hcs` is loaded in `HdfUartDeviceInit`, and the corresponding serial port pins are initialized. The code for testing the serial port at the application layer is as follows:
```
DevHandle uart_handle = UartOpen(0);
UartSetBaud(uart_handle, 115200);
...
attr.dataBits = UART_ATTR_DATABIT_8;
attr.parity = UART_ATTR_PARITY_NONE;
attr.stopBits = UART_ATTR_STOPBIT_1;
ret = UartSetAttribute(uart_handle, &attr);
ret = UartWrite(uart_handle, send_data, strlen(send_data));
ret = UartRead(uart_handle, recv_data, sizeof(recv_data) - 1);
...
```
## OpenHarmony Component Porting
The compilation option entry of the subsystem is in the `config.json` file of the corresponding product. The following uses `//vendor/asrmicro/wifi_demo/config.json` as an example.
### LWIP component
The source code of the lwIP component is stored in `//third_party/lwip`. The kernel in Openharmony is customized in `//kernel/liteos_m/components/net/lwip-2.1`, including the redefinition of some interfaces and structures.
For details about the porting process, see [lwIP Module Adaptation](https://gitee.com/openharmony/docs/blob/master/en/device-dev/porting/porting-chip-board-lwip.md).
In this example, the path for setting lwip in the `config.json` file is as follows:
```
"subsystem": "kernel",
"components": [
{
"component": "liteos_m",
"features": [
"ohos_kernel_liteos_m_lwip_path = \"//device/soc/asrmicro/asr582x/liteos_m/components/net/lwip-2.1\""
]
}
]
```
Enable lwIP compilation in the `kernel_config/debug.config` file.
```
LOSCFG_NET_LWIP=y
```
### Security Component
For the security component, enable the corresponding options in `config.json`. In this example, mbedtls (`//third_party/mbedtls`) in the third-party library is used as the encryption module. The options are as follows:
```
"subsystem": "security",
"components": [
{ "component": "huks", "features":
[
...
"ohos_security_huks_mbedtls_porting_path = \"//device/soc/asrmicro/asr582x/liteos_m/components/mbedtls\""
]
}
]
```
In the preceding directory, you need to configure mbedtls. For details, see `config/config_liteos_m.h`. Note that if the RNG capability of mbedtls is used (for example, the dsoftbus component is used in `//foundation/communication/dsoftbus/adapter/common/mbedtls/softbus_adapter_crypto.c`), the entropy source for generating random numbers must be specified. In this example, the hardware random number capability of the ASR582X is used. You need to enable the following macro:
```
#define MBEDTLS_ENTROPY_HARDWARE_ALT
```
After this macro is enabled, the `entropy_hardware_alt` interface needs to be implemented. For details, see `library/entropy_hardware_alt.c`.
### wifi_lite Component
The options of the wifi_lite component are as follows:
```
"subsystem": "communication",
"components": [
{ "component": "wifi_lite", "features":[] }
]
```
Wi-Fi-related functions are implemented in `//device/soc/asrmicro/asr582x/liteos_m/sdk/hal/src/wifi_adapter.c`.
This example also provides a demo that uses the `wifi_lite` interfaces. For details, see `//vendor/asrmicro/wifi_demo/tests/wifi/wifi_app.c`. The following two connection test commands are provided:
Table 1 ASR Wi-Fi connection commands
| Command | Parameter | Description |
|------------|--------|--------|
| wifi_open | sta [SSID] [KEY] | Connection routing command, for example, `wifi_open sta ASR_AP test123456`.|
| wifi_close | N/A | Command for disconnecting a connection. |
### XTS component
To adapt the XTS component, for example, `//vendor/asrmicro/xts_demo/config.json`, add the following component options:
```
"subsystem": "xts",
"components": [
{ "component": "xts_acts", "features":
[
"enable_ohos_test_xts_acts_use_thirdparty_lwip = true"
]
},
{ "component": "xts_tools", "features":[] }
]
```
The XTS function is also organized using `list`. You can add or delete modules in the `config.json` file by referring to [Modular Compilation].
```
"xts_list": [
{
"enable": "true",
"xts_modules": [
"ActsKvStoreTest",
"ActsDfxFuncTest",
"ActsHieventLiteTest",
"ActsSamgrTest",
"ActsParameterTest",
"ActsWifiServiceTest",
"ActsWifiIotTest",
"ActsBootstrapTest"
]
}
],
```
### dsoftbus component
The dsoftbus component provides the discovery, connection, networking, and transmission capabilities between devices. This solution uses the DSoftBus capability between Wi-Fi devices as an example.
Dependent components: lwIP, security, and wifi_lite.
Prerequisites: The device is connected to a router, and all networking devices are in the same LAN.
The options of the dsoftbus component are as follows:
```
"subsystem": "communication",
"components": [
{ "component": "dsoftbus", "features":[] }
]
```
The dsoftbus test demo is provided in `//vendor/asrmicro/wifi_demo`. To enable this function, modify `//vendor/asrmicro/wifi_demo/tests/BUILD.gn`.
```
declare_args() {
asr_dsoftbus_test = true --- Enable dsoftbus demo compilation.
}
```
Add the dsoftbus_test module to the `//vendor/asrmicro/wifi_demo/config.json` file.
```
"tests_list": [
{
"enable": "true",
"test_modules": [
"wifi_test",
"dsoftbus_test" --- Enable the dsoftbus_test module.
]
}
]
```
For details about the startup interface of the dsoftbus component, see `//vendor/asrmicro/wifi_demo/tests/dsoftbus/dsoftbus_app.c`.
```
InitSoftBusServer();
```
At least 80 KB RAM needs to be reserved for the running of the DSoftBus component. If the resources are insufficient, other parts such as the lwIP component can be tailored.
`//kernel_liteos_m/blob/master/components/net/lwip-2.1/porting/include/lwip/lwipopts.h`:
```
#define TCPIP_THREAD_STACKSIZE 0x2000 --- Reduce the size of the TCP/IP task stack.
```
The `-fPIC` compilation option is added to the `communication_dsoftbus` repository. In this way, the compiler generates position-independent code and uses relative addresses. However, the LiteOS-M core uses a static library, which is not recommended.
You are advised to manually comment out the `-fPIC` compilation option in the following files:
`//foundation/communication/dsoftbus/core/common/BUILD.gn`
`//foundation/communication/dsoftbus/core/frame/BUILD.gn`
`//foundation/communication/dsoftbus/sdk/BUILD.gn`
`//foundation/communication/dsoftbus/components/nstackx_mini/nstackx_ctrl/BUILD.gn`
The DSoftBus networking requires device authentication. In the R&D phase, you can skip the authentication and focus on the networking and transmission capabilities. You need to replace the `HandleReceiveDeviceId` function in the `//foundation/communication/dsoftbus/core/authentication/src/auth_manager.c` file with the following implementation:
```
void HandleReceiveDeviceId(AuthManager *auth, uint8_t *data)
{
uint8_t tempKey[SESSION_KEY_LENGTH] = {0};
if (auth == NULL || data == NULL) {
SoftBusLog(SOFTBUS_LOG_AUTH, SOFTBUS_LOG_ERROR, "invalid parameter");
return;
}
if (AuthUnpackDeviceInfo(auth, data) != SOFTBUS_OK) {
SoftBusLog(SOFTBUS_LOG_AUTH, SOFTBUS_LOG_ERROR, "AuthUnpackDeviceInfo failed");
AuthHandleFail(auth, SOFTBUS_AUTH_UNPACK_DEVID_FAILED);
return;
}
if (auth->side == SERVER_SIDE_FLAG) {
if (EventInLooper(auth->authId) != SOFTBUS_OK) {
SoftBusLog(SOFTBUS_LOG_AUTH, SOFTBUS_LOG_ERROR, "auth EventInLooper failed");
AuthHandleFail(auth, SOFTBUS_MALLOC_ERR);
return;
}
if (AuthSyncDeviceUuid(auth) != SOFTBUS_OK) {
AuthHandleFail(auth, SOFTBUS_AUTH_SYNC_DEVID_FAILED);
}
(void)memset_s(tempKey, SESSION_KEY_LENGTH, 1, SESSION_KEY_LENGTH);
AuthOnSessionKeyReturned(auth->authId, tempKey, SESSION_KEY_LENGTH);
return;
}
//VerifyDeviceDevLvl(auth); --- Comment out the authentication process.
(void)memset_s(tempKey, SESSION_KEY_LENGTH, 1, SESSION_KEY_LENGTH);
AuthOnSessionKeyReturned(auth->authId, tempKey, SESSION_KEY_LENGTH);
}
```
After correct configuration, compilation, and burning, the device uses the wifi_open command to connect to the router. After the connection is successful, the device automatically performs networking.
The adaptation process of other components is similar to that of other vendors.
## To-do
- Adding BLE support
- Diversifying Wi-Fi test commands
# Mini-System Devices with Screens — Bestechnic SoC Porting Case
This document exemplifies the porting procedure for a development board on a mini-system device with a screen – an intelligent switch panel. It uses the BES multi-modal V200Z-R development board powered by the Bestechnic BES2600W SoC as an example. Components such as `ace_engine_lite`, `graphic_ui`, `aafwk_lite`, `appexecfwk_lite`, and `HDF` are adapted based on the OpenHarmony LiteOS-M kernel. This example uses the board-SoC separation solution as the porting architecture, the Newlib C or Musl C library as the toolchain, and GN and Kconfig graphical configuration for LiteOS-M kernel compilation.
## Compilation and Building
### Directory Planning
This example uses an improved SoC porting architecture. The original SoC adaptation directory is as follows:
```
device
└── <device_company>
   └── <device_name>
```
This adaptation directory has a downside: To use the Hi3861 SoC on the BearPi-HM Nano or HiSpark Pegasus development board, you need to place a copy of the code in the directory of both development boards. To solve this problem, the board vendor is decoupled from the SoC vendor in this example, by following the board-SoC decoupling design ideas. The SoC adaptation directory used in this example is as follows:
```
device
├── board --- Board vendor directory
│ └── fnlink --- Board vendor name: Fn-Link
│ └── v200zr --- Board name: v200zr
└── soc --- SoC vendor directory
└── bestechnic --- SoC vendor: Bestechnic
└── bes2600 --- SoC Series: The bes2600 series includes bes2600w.
```
The planned product demo directory is as follows:
```
vendor
└── bestechnic --- Vendor of the product demo.
└── display_demo --- Product demo name.
```
### Precompilation Adaptation
Before porting, you need to perform precompilation adaptation.
To do so, use the `hb set` command to set environment variables such as the root directory, board directory, product directory, and board company name of the entire project.
The specific procedure is as follows:
1. Add the `config.json` file to the `vendor/bestechnic/display_demo` directory to describe the board and kernel information used by the product demo. The following is an example of the description:
```
{
"product_name": "display_demo", --- Product name to display in the hb set drop-down list.
Type of the "type": "mini", --- Build system type, which can mini, small, or standard.
Version of the "version": "3.0", --- Build system version, which can be 1.0, 2.0, or 3.0.
"device_company": "fnlink", --- Board vendor name, which is used to find the /device/board/fnlink directory during compilation.
"board": "v200zr", --- Board name, which is used to find the /device/board/fnlink/v200zr directory during compilation.
"kernel_type": "liteos_m", --- Kernel type. OpenHarmony supports multiple kernels, and one board may be adapted to multiple kernels. Therefore, you need to specify a kernel for compilation.
"kernel_version": "3.0.0", --- Kernel version. A board may be adapted to multiple Linux kernel versions. Therefore, you need to specify a kernel version for compilation.
"subsystems": [ ] --- Subsystem to be compiled and built.
}
```
2. Add the `config.gni` file to the `device/board/fnlink/v200zr/liteos_m` directory to describe the board and kernel used in the product demo. The following is an example of the description:
```
# Kernel type, e.g. "linux", "liteos_a", "liteos_m".
kernel_type = "liteos_m" --- Kernel type, which corresponds to kernel_type in the config.json file.
# Kernel version.
kernel_version = "3.0.0" --- Kernel version, which corresponds to kernel_version in the config.json file.
```
3. Verify the `hb set` configuration:
Run the `hb set` command, enter the project root directory, and press `Enter`. The `hb` command traverses all `config.json` files in the `//vendor/<product_company>/<product_name>` directory and provides product compilation options. In the `config.json` file, `product_name` indicates the product name, `device_company` and `board` are used to locate the `//device/board/<device_company>/<board>` directory and find the matching `<any_dir_name>/config.gni` file. If multiple file matches are found, it indicates that the board has been adapted to multiple kernels. In this case, `kernel_type` and `kernel_version` in the `config.json` file can be used to uniquely match the `config.gni` file and thereby determine the board with which kernel needs to be compiled and adapted. If the information shown below is displayed, the `hb set` configuration is correct.
![hb set](figure/bes2600_hb_set.png)
​ You can run the `hb env` command to view the selected precompilation environment variables.
![hb env](figure/bes2600_hb_env.png)
Before running the `hb build` command, complete the LiteOS-M kernel adaptation. For details, see [Kernel Porting](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/porting-bes2600w-on-minisystem-display-demo.md#%E5%86%85%E6%A0%B8%E7%A7%BB%E6%A4%8D).
## Kernel Porting
To port the kernel, you need to complete the LiteOS-M Kconfig adaptation, GN compilation and building, and minimum adaptation for kernel startup.
### LiteOS-M Kconfig Adaptation
Run the `make menuconfig` command in the `//kernel/liteos_m` directory to select compilation configuration options. In the `Makefile` file, the `hb env` result is converted into environment variables, that is, `PRODUCT_PATH`, `DEVICE_PATH`, and `BOARD_COMPANY`. The sample code is as follows:
```
$(foreach line,$(shell hb env | sed 's/\[OHOS INFO\]/ohos/g;s/ /_/g;s/:_/=/g' || true),$(eval $(line)))
ifneq ($(ohos_kernel),liteos_m)
$(error The selected product ($(ohos_product)) is not a liteos_m kernel type product)
endif
--- Convert each line of hb env to a variable. For example, convert [OHOS INFO] device company: fnlink to ohos_device_company=fnlink.
...
ifeq ($(BOARD_COMPANY),)
BOARD_COMPANY:=$(ohos_device_company)
endif
...
export BOARD_COMPANY
--- Convert ohos_device_company to the BOARD_COMPANY environment variable.
```
Use the exported environment variables in the `//kernel/liteos_m/Kconfig` file. `Kconfiglib` uses `ulfalizer` to develop the Python-based version. In the [source code](https://github.com/ulfalizer/Kconfiglib), as drscribed in [function description](https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/kconfig/kconfiglib.py), the keyword `orsource` is used. In this keyword, `o` indicates `optional`, that is, the file is optional. `r` indicates `relative`, that is, the path of the file relative to the current file.
```
config SOC_COMPANY
string "SoC company name to locate soc build path"
help
This option specifies the SoC company name, used to locate the build path for soc. This option is set by the
SoC's Kconfig file, and should be exactly the same with SoC company path, and the user should generally avoid
modifying it via the menu configuration.
orsource "../../device/board/*/Kconfig.liteos_m.shields" --- Load the configurations of all extension boards. To allow the extension boards provided by board vendor A to be used by board vendor B, the asterisk (*) instead of BOARD_COMPANY is used. As OpenHarmony supports the multi-kernel design, the Kconfig file uses liteos_m as the suffix. During board adaptation, the actual kernel name can be used as the suffix for extension during kernel adaptation.
orsource "../../device/board/$(BOARD_COMPANY)/Kconfig.liteos_m.defconfig.boards" --- Load all predefined board configurations of BOARD_COMPANY.
choice
prompt "Board Selection"
The orsource "../../device/board/$(BOARD_COMPANY)/Kconfig.liteos_m.boards" --- Provide a list of available boards.
endchoice
orsource "../../device/soc/*/Kconfig.liteos_m.defconfig" --- Load the default configuration definitions of all SoCs.
choice
prompt "SoC Series Selection"
orsource "../../device/soc/*/Kconfig.liteos_m.series" --- Provide a list of available SoC series.
endchoice
orsource "../../device/soc/*/Kconfig.liteos_m.soc" --- Load all SoC configurations.
```
According to the `//kernel/liteos_m/Kconfig` file, the following `Kconfig` files need to be added to the `//device/board/fnlink` directory for adaptation:
```
.
├── v200zr --- Configuration of the v200zr
│ ├── Kconfig.liteos_m.board --- Configuration options of the v200zr board
│ ├── Kconfig.liteos_m.defconfig.board --- Default configuration items of the v200zr board
│   └── liteos_m
│   └── config.gni
├── Kconfig.liteos_m.boards --- Board configuration of Fn-Link
├── Kconfig.liteos_m.defconfig.boards --- Default board configuration of Fn-Link
├── Kconfig.liteos_m.shields --- Extension board configuration of Fn-Link
└── shields --- Extension board directory of Fn-Link
├── v200zr-t0 --- Expansion board v200zr-t0 of Fn-Link
│   ├── Kconfig.liteos_m.defconfig.shield --- Default configuration of the expansion board v200zr-t0
│   └── Kconfig.liteos_m.shield --- Configuration of the expansion board v200zr-t0
├── v200zr-t1
│   ├── Kconfig.liteos_m.defconfig.shield
│   └── Kconfig.liteos_m.shield
└── Kconfig.liteos_m.shields
```
In `v200zr/Kconfig.liteos_m.board`, you need to set the board configuration options and the dependent `SoC` as follows:
```
config BOARD_v200zr
bool "select board v200zr"
depends on SOC_BES2600W --- The v200zr board uses the bes2600w SoC. Therefore, the v200zr board configuration options are available only when the bes2600w SoC is selected.
```
In `v200zr/Kconfig.liteos_m.defconfig.board`, the default name of `BOARD` is defined as `"v200zr"`.
```
if BOARD_v200zr
config BOARD
string --- No content is defined for string. Therefore, it is not visible to users.
default "v200zr"
endif # BOARD_v200zr
```
According to the `//kernel/liteos_m/Kconfig` file, the following `Kconfig` files need to be added to the `//device/soc/bestechnic` directory for adaptation:
```
.
├── bes2600 --- bes2600 SoC series
│   ├── Kconfig.liteos_m.defconfig.bes2600w --- Configuration of the bes2600w SoC series provided by Bestechnic
│   ├── Kconfig.liteos_m.defconfig.series --- Default configuration of the bes2600 provided by Bestechnic
│   ├── Kconfig.liteos_m.series --- Configuration of the bes2600 SoC series provided by Bestechnic
│   └── Kconfig.liteos_m.soc --- Configuration of the bes2600 SoC provided by Bestechnic
├── Kconfig.liteos_m.defconfig --- Default SoC configuration of Bestechnic
├── Kconfig.liteos_m.series --- Configuration of the SoC series provided by Bestechnic
└── Kconfig.liteos_m.soc --- Configuration of the SoC provided by Bestechnic
```
In the `bes2600/Kconfig.liteos_m.series` file, configure the `bes2600 SoC series` and SoC architecture as follows:
```
config SOC_SERIES_BES2600 --- bes2600 SoC series configuration options
bool "Bestechnic 2600 Series"
select ARM --- When bes2600 is selected, the ARM architecture is selected by default.
select SOC_COMPANY_BESTECHNIC --- When bes2600 is selected, bestechnic is selected by default. The driver depends on the macro configuration. You can select the configuration to compile the driver of the corresponding vendor.
select CPU_CORTEX_M33 --- When bes2600 is selected, cortex-m33 CPU is selected by default.
help
Enable support for Bestechnic 2600 series
```
In the `bes2600/Kconfig.liteos_m.soc` file, provide the number of specific SoCs under the `bes2600 SoC series` as follows:
```
choice
prompt "Bestechnic 2600 series SoC"
depends on SOC_SERIES_BES2600 --- The following configuration options are displayed only when bes2600 Series is selected:
config SOC_BES2600W --- Add the bes2600w SoC configuration option.
bool "SoC BES2600w"
endchoice
```
In the `bes2600/Kconfig.liteos_m.defconfig.series` file, provide the following configuration that is used by default when the bes2600 SoC series is selected:
```
if SOC_SERIES_BES2600 --- The following default configuration options are added only when the bes2600 series is selected:
rsource "Kconfig.liteos_m.defconfig.bes2600w" --- Add the default configuration that is used by default when bes2600 SoC series is selected.
config SOC_SERIES --- Add the configuration that is used by default when SOC_SERIES is selected:
string
default "bes2600"
endif
```
When the configuration is complete, set the `defconfig` storage path of `make menuconfig` based on the `kernel/liteos_m/Makefile` file.
```
ifeq ($(TEE:1=y),y)
tee = _tee
endif
ifeq ($(RELEASE:1=y),y)
CONFIG ?= $(PRODUCT_PATH)/kernel_configs/release$(tee).config
else
CONFIG ?= $(PRODUCT_PATH)/kernel_configs/debug$(tee).config --- The configuration file is saved in $(CONFIG) and is defined by the product.
endif
...
update_config menuconfig:
$(HIDE)test -f "$(CONFIG)" && cp -v "$(CONFIG)" .config && menuconfig $(args) && savedefconfig --out "$(CONFIG)"
```
In this example, the configuration file of `defconfig` is saved in `$(PRODUCT_PATH)/kernel_configs/debug.config`. It is empty by default upon creation. The directory and file structure of the product is as follows:
```
.
└── display_demo
├── config.json
└── kernel_configs
└── debug.config
```
When the configuration is complete, run the `make menuconfig` command in the `kernel/liteos_m` directory to select `SoC Series`/`SoC`/`Board`.
![board make menuconfig](figure/bes2600_board_make_menuconfig.png)
The result is automatically saved in `$(PRODUCT_PATH)/kernel_configs/debug.config` and will be exported when `make menuconfig` is executed.
### GN Build Adaptation
The graphical configuration result of `Kconfig` generated in the previous step can be used as the input of GN build to determine whether to build different modules. In addition, to solve the problem of arbitrary use of `include` during GN build, modular compilation is used for kernel compilation, streamlining the entire compilation logic. For details, see *LiteOS-M Kernel BUILD.gn Compilation Guide*.
In the `kernel/liteos_m/BUILD.gn` file, the compilation entrances of `Board` and `SoC` are specified as `//device/board/fnlink` and `//device/soc/bestechnic`.
```
deps += [ "//device/board/$device_company" ]
deps += [ "//device/soc/$LOSCFG_SOC_COMPANY" ]
```
Add the following content to `//device/board/fnlink/BUILD.gn`:
```
if (ohos_kernel_type == "liteos_m") { --- In the multi-kernel design, macros need to be used to isolate the adapted LiteOS-M kernel.
import("//kernel/liteos_m/liteos.gni") --- Import the kernel GN template.
module_name = get_path_info(rebase_path("."), "name") --- Dynamically obtain the current directory and use it as the module name, eliminating the need for manual synchronization between the directory and module name.
module_group(module_name) { --- Use the module_group template.
modules = [ --- Add the modules to be built.
]
}
}
```
Modify the `//device/soc/bestechnic/BUILD.gn` file in a similar manner.
### Kernel Boot Adaptation
The system boot process consists of three phases:
| Phase | Partitioning Planning | Description |
| --------- | ------------------------ | ----------------------------- |
| BOOT1 | [0, 0x10000] | The firmware is started. |
| BOOT2 | [0x2C010000, 0x2C020000] | The OTA update starts.|
| RTOS_MAIN | [0x2C080000, 0x2C860000] | The kernel is started. |
In the third phase where the kernel is started, the file to be adapted is saved in `//device/soc/bestechnic/bes2600/liteos_m/sdk/bsp/rtos/liteos/liteos_m/board.c`.
The general idea of kernel boot adaptation is as follows:
1. `os_vector_init` is used to initialize interrupt vectors and interrupt processing functions.
2. `osKernelInitialize` is used to initialize the kernel.
3. The `board_main` thread is created to initialize the chip platform.
4. The kernel starts up and schedules the `osKernelStart` thread.
This section describes step 3 in detail. Other steps involve invoking of kernel functions and are not described here.
In step 3, before starting `OHOS_SystemInit`, `board_main` needs to complete the necessary actions as follows:
```
...
if(!ret) {
...
OhosSystemAdapterHooks(); --- Configure the hook during system boot and complete the printing and driver initialization before OHOS_SystemInit is started.
...
OHOS_SystemInit(); --- Start the OpenHarmony service and initialize components.
}
....
```
The `OhosSystemAdapterHooks` function is in the `device/soc/bestechnic/bes2600/liteos_m/components/utils/src/hm_sys.c` file, as shown below:
```
int OhosSystemAdapterHooks(void)
{
init_trace_system(); --- Initialize the printing function.
DeviceManagerStart(); --- Call the DeviceManagerStart function to initialize the HDF driver. This process is implemented by calling the driver configuration file hdf.hcs in the board code and implementing the drivers source code.
return 0;
}
```
### littlefs File System Porting
The `V200Z-R` development board uses the `Nor Flash` that supports `XIP` and has a maximum size of `32 MB`. The `example` file system can be used. During the adaptation, place the file system configuration file in the specified path. The file system image is then automatically generated based on the configuration and packaged into the burning package.
1. Specify the directory for storing the file system `config.json` by using `flash_partition_dir`.
```
"flash_partition_dir": "fs" --- Store the file system configuration file in the vendor/bestechnic/display_demo/fs directory.
```
2. Place the following items in the `vendor/bestechnic/display_demo/fs` directory:
- `wifi_Download_cfg.yaml`: configuration file for image burning. The partitions can be adjusted as required.
- `/data/data`: The first /`data` is the root directory to mount. The second `data` is the `data` directory in the root directory. You can place the configuration file in the second `data` directory or in any directory at the same level. During packaging, the whole root directory is packaged.
3. Set the following items in the `config.json` file based on the `wifi_Download_cfg.yaml` file:
- `fs_src`: name under which the file system is mounted.
- `fs_name`: name of the generated file system.
- `block_size`: size of the read data block. Set it to `4K` alignment and do not change the value.
- `fs_size`: size of the generated file system.
- `burn_name`: size of the burnt `bin` name.
- `enable`: whether to generate the file system.
4. In the `//device/soc/bestechnic/bes2600/liteos_m/components/hdf_config/hdf.hcs` file, configure the start address for burning the file system, size of the file system, and size of the read data block (`block_size`). The reference configuration is as follows:
```
misc {
fs_config {
example_config {
match_attr = "littlefs_config";
mount_points = ["/data"];
partitions = [10];
block_size = [4096];
block_count = [1024];
}
}
storage_config {
flash_config {
match_attr = "flash_config";
partitions = [10];
owner = [0];
description = ["littlefs"];
start_addr = [0xB60000];
length = [0x400000];
options = [3];
}
}
}
```
In `device/soc/bestechnic/bes2600/liteos_m/components/fs/fs_init.c`, load data through `hdf` and read and write to `flash` as follows:
```
static int32_t FsDriverInit(struct HdfDeviceObject *object)
{
if (object == NULL) {
return HDF_FAILURE;
}
if (object->property) {
if (FsGetResource(fs, object->property) != HDF_SUCCESS) {
HDF_LOGE("%s: FsGetResource failed", __func__);
return HDF_FAILURE;
}
}
for (int i = 0; i < sizeof(fs) / sizeof(fs[0]); i++) {
if (fs[i].mount_point == NULL)
continue;
fs[i].lfs_cfg.read = littlefs_block_read;
fs[i].lfs_cfg.prog = littlefs_block_write;
fs[i].lfs_cfg.erase = littlefs_block_erase;
fs[i].lfs_cfg.sync = littlefs_block_sync;
fs[i].lfs_cfg.read_size = 256;
fs[i].lfs_cfg.prog_size = 256;
fs[i].lfs_cfg.cache_size = 256;
fs[i].lfs_cfg.lookahead_size = 16;
fs[i].lfs_cfg.block_cycles = 1000;
int ret = mount(NULL, fs[i].mount_point, "littlefs", 0, &fs[i].lfs_cfg);
HDF_LOGI("%s: mount fs on '%s' %s\n", __func__, fs[i].mount_point, (ret == 0) ? "succeed" : "failed");
}
return HDF_SUCCESS;
}
```
### C Library Adaptation
In the mini system, adapting the C library is a complex process. For details, see *Solution to Smooth Switchover Between musl and newlib for LiteOS-M Kernel*. The toolchain uses the `newlib` C library of the [gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2](https://gitee.com/link?target=https%3A%2F%2Fdeveloper.arm.com%2F-%2Fmedia%2FFiles%2Fdownloads%2Fgnu-rm%2F10.3-2021.10%2Fgcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2). In light of this, the `newlib` C library is used for system porting. Select `newlib` in `make menuconfig` of the kernel, as shown below.
![image-20211212191013553](figure/bes2600_newlib_make_menuconfig.png)
#### malloc Adaptation
For details, see [The Red Hat newlib C Library-malloc](https://sourceware.org/newlib/libc.html#malloc). You can use either of the following methods to implement malloc adaptation:
- Implement the `_sbrk_r` function. In this method, the memory allocation function in `newlib` is used.
- Implement `_malloc_r`, `_realloc_r`, `_reallocf_r`, `_free_r`, `_memalign_r`, and `_malloc_usable_size_r`. In this method, the memory allocation function in the kernel can be used.
To facilitate memory allocation algorithm optimization and fault locating based on services, the latter method is used in this example.
First, as the symbols of the functions in the second method already exist in `newlib`, you need to use the `wrap` link option of `gcc` to replace these function symbols with the kernel implementation code in `//kernel/liteos_m/kal/libc/newlib/porting/src/malloc.c`.
Then, add the `wrap` link option of these functions to `//device/board/fnlink/v200zr/liteos_m/config.gni`.
```
board_ld_flags += [
"-Wl,--wrap=_malloc_r",
"-Wl,--wrap=_realloc_r",
"-Wl,--wrap=_reallocf_r",
"-Wl,--wrap=_free_r",
"-Wl,--wrap=_memalign_r",
"-Wl,--wrap=_malloc_usable_size_r",
]
```
#### vsprintf and Related Adaptation
Implement `vprintf`, `vfprintf`, `printf`, `snprintf`, and `sprintf`. For details, see [vfprintf](https://sourceware.org/newlib/libc.html#vfprintf).
Similar to `malloc` adaptation, the implementation of these functions must be provided first, that is, `//device/soc/bestechnic/bes2600/liteos_m/components/utils/src/printf.c`. In this example, the friendly implementation of the open-source protocol is used. Different from `malloc` adaptation, this function is provided by the SoC vendor. This is because the implementation size varies in terms of printing based on the project requirements, and therefore the kernel cannot provide a unified implementation.
Then, add the `wrap` link option of these functions to `//device/board/fnlink/v200zr/liteos_m/config.gni`.
```
board_ld_flags += [
"-Wl,--wrap=printf",
"-Wl,--wrap=sprintf",
"-Wl,--wrap=snprintf",
"-Wl,--wrap=vsnprintf",
"-Wl,--wrap=vprintf",
]
```
#### open and Related Adaptation
The adaptation is implemented by the kernel and does not need attention from the SoC. The kernel file `//kernel/liteos_m/kal/libc/newlib/porting/src/fs.c` has been adapted to the `_read`, `_write`, and other related functions of `newlib`, as shown below.
```
...
ssize_t _read(int fd, void *buf, size_t nbyte)
{
return LOS_Read(fd, buf, nbyte);
}
ssize_t _write(int fd, const void *buf, size_t nbyte)
{
return LOS_Write(fd, buf, nbyte);
}
off_t _lseek(int fd, off_t offset, int whence)
{
return LOS_Lseek(fd, offset, whence);
}
...
```
## Board-Level OS Porting
### Driver Porting
#### Porting the HDF Driver for the SoC Platform
Driver adaptation files are stored in `drivers/adapter/platform`, including `gpio`, `i2c`, `pwm`, `spi`, `uart`, and `watchdog`, which are loaded using the `HDF` mechanism. This section uses `gpio` as an example.
##### GPIO Driver Adaptation
The `gpio` driver adaptation requires building adaptation and source code adaptation.
The `//drivers/adapter/platform/gpio/BUILD.gn` file describes the building adaptation of the `gpio` driver, as shown below:
```
module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO) --- If the GPIO configuration switch of the HDF is enabled, the following is built:
module_name = get_path_info(rebase_path("."), "name")
hdf_driver(module_name) {
sources = []
if (defined(LOSCFG_SOC_COMPANY_BESTECHNIC)) { --- If the Bestechnic SoC configuration switch is enabled, the Bestechnic GPIO driver is built.
sources += [ "gpio_bes.c" ]
}
include_dirs = [ "." ]
}
```
The `//drivers/adapter/platform/gpio/gpio_bes.c` file describes the source code adaptation of the Bestechnic GPIO driver.
First, load the basic driver adaptation framework based on OpenHarmony `HDF`, as shown below:
```
struct HdfDriverEntry g_GpioDriverEntry = {
.moduleVersion = 1,
.moduleName = "BES_GPIO_MODULE_HDF",
.Bind = GpioDriverBind,
.Init = GpioDriverInit,
.Release = GpioDriverRelease,
};
HDF_INIT(g_GpioDriverEntry); --- Load the GPIO driver through HDF_INIT.
```
Then, obtain the `hcs` parameter for initialization as follows:
```
static int32_t GpioDriverInit(struct HdfDeviceObject *device)
{
int32_t ret;
struct GpioCntlr *gpioCntlr = NULL;
if (device == NULL) {
HDF_LOGE("%s: device is NULL", __func__);
return HDF_ERR_INVALID_PARAM;
}
gpioCntlr = GpioCntlrFromDevice(device); --- Obtain the GPIO configuration.
if (gpioCntlr == NULL) {
...
```
#### Porting the HDF Drivers of Peripheral Components on the Board
Peripheral components are connected to the board through the `SoC` bus. In this example, the peripheral component is a display, whose driver adaptation code is stored in the `//device/board/fnlink/drivers/liteos_m` directory.
##### Display Driver Adaptation
The display driver adaptation process is similar to the `SoC` driver adaptation process. In the `//device/board/fnlink/drivers/liteos_m/display/BUILD.gn` file, load the driver module based on the `hdf_driver` template, as shown below:
```
module_name = get_path_info(rebase_path("."), "name")
hdf_driver(module_name) {
sources = [
"zzw395.c",
]
include_dirs = [
"//drivers/peripheral/display/interfaces/include",
...
]
}
```
In the `//device/board/fnlink/drivers/liteos_m/display/zzw395.c` file, load the display driver based on HDF, as shown below:
```
static struct HdfDriverEntry g_ZZW395DriverEntry = {
.moduleVersion = 1,
.moduleName = "HDF_PANEL_ZZW395",
.Bind = PanelDriverBind,
.Init = PanelDriverInit,
.Release = PanelDriverRelease,
};
HDF_INIT(g_ZZW395DriverEntry);
```
Configure the driver parameters based on `hcs`, which are loaded during `PanelDriverInit` initialization. The sample code is as follows:
```
static int32_t PanelDriverInit(struct HdfDeviceObject *object)
{
if (object == NULL) {
return HDF_FAILURE;
}
HDF_LOGD("%s entry !!!", __func__);
if (object->property) {
if (PanelGetResource(&priv, object->property) != HDF_SUCCESS) {
HDF_LOGE("%s: PanelGetResource failed", __func__);
return HDF_FAILURE;
}
}
...
```
### Adapting OpenHarmony Subsystems
The adaptation of OpenHarmony subsystems consists of two parts:
- Add the target subsystem and component to the `config.json` file so that the component can be included in the compilation by the compilation system.
- Perform hardware adaptation or optional software adaptation for the `HAL` layer APIs of the component.
#### Communication Subsystem Adaptation
##### wifi_lite Component Adaptation
Add the `wifi_lite` component of the `communication` subsystem to the `config.json` file.
```
{
"subsystem": "communication",
"components": [
{
"component": "wifi_lite",
"optional": "true"
}
]
},
```
The `wifi_lite` component is described in the `//build/lite/components/communication.json` file as follows:
```
{
"component": "wifi_lite",
...
"targets": [
"//foundation/communication/wifi_lite:wifi" --- wifi_lite in the compilation targets
],
...
},
```
In the `//foundation/communication/wifi_lite/BUILD.gn` file, describe the path of the API header file to be adapted as follows:
```
config("include") {
include_dirs = [ "interfaces/wifiservice" ] --- The wifi_lite component provides the header file but not the implementation. Therefore, it exposes the adaptation directory to the hardware vendor for adaptation. The vendor provides the Wi-Fi protocol stack source code for implementation.
}
group("wifi") {
public_configs = [ ":include" ]
}
```
In this example, Wi-Fi is provided by `SoC`. Therefore, the Wi-Fi adaptation source code is stored in the `//device/soc/bestechnic/hals/communication/wifi_lite/wifiservice` directory of `SoC`, which contains `wifi_device.c` and `wifi_hotspot.c` to adapt to `wifi_device.h` and `wifi_hotspot.h`, respectively. The sample code is as follows:
```
...
WifiErrorCode Scan(void) --- Wi-Fi hotspot scanning function in wifi_device.c, which is used to adapt to the Scan function in wifi_device.h.
{
WifiErrorCode ret = ERROR_WIFI_BUSY;
if (IsWifiActive() != WIFI_STA_ACTIVE)
return ERROR_WIFI_IFACE_INVALID;
if (g_HalHmosWifiInfo.scan_state == SCAN_REQUEST ||
g_HalHmosWifiInfo.scan_state == SCAN_TRIGGER)
return ERROR_WIFI_BUSY;
HalHmosWifiLock();
ret = ((HalHmosSendEvent(HMOS_ON_WIFI_SCAN_STATE_CHANGED, NULL) == 0) ? WIFI_SUCCESS : ERROR_WIFI_BUSY);
HalHmosWifiUnLock();
return ret;
}
...
int GetSignalLevel(int rssi, int band) --- Function in wifi_hotspot.c for obtaining Wi-Fi hotspot parameters, which is used to adapt to the GetSignalLevel function in wifi_hotspot.h.
{
if (band == HOTSPOT_BAND_TYPE_2G) {
if (rssi >= RSSI_LEVEL_4_2_G)
return RSSI_LEVEL_4;
if (rssi >= RSSI_LEVEL_3_2_G)
return RSSI_LEVEL_3;
if (rssi >= RSSI_LEVEL_2_2_G)
return RSSI_LEVEL_2;
if (rssi >= RSSI_LEVEL_1_2_G)
return RSSI_LEVEL_1;
}
if (band == HOTSPOT_BAND_TYPE_5G) {
if (rssi >= RSSI_LEVEL_4_5_G)
return RSSI_LEVEL_4;
if (rssi >= RSSI_LEVEL_3_5_G)
return RSSI_LEVEL_3;
if (rssi >= RSSI_LEVEL_2_5_G)
return RSSI_LEVEL_2;
if (rssi >= RSSI_LEVEL_1_5_G)
return RSSI_LEVEL_1;
}
return ERROR_WIFI_INVALID_ARGS;
}
```
##### lwIP Component Adaptation
By default, `lwip` is configured in the `LiteOS-M kernel` directory. Therefore, you can include the `lwip` directory in the `kernel` component for compilation. The sample code is as follows:
```
{
"subsystem": "kernel",
"components": [
{
"component": "liteos_m",
"features": [
"ohos_kernel_liteos_m_lwip_path = \"//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1\"" --- Specify the SoC vendor directory for compilation.
]
}
]
},
```
The `//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/BUILD.gn` file describes the compilation of `lwip` as follows:
```
import("//kernel/liteos_m/liteos.gni")
import("$LITEOSTHIRDPARTY/lwip/lwip.gni")
import("$LITEOSTOPDIR/components/net/lwip-2.1/lwip_porting.gni")
module_switch = defined(LOSCFG_NET_LWIP_SACK)
module_name = "lwip"
kernel_module(module_name) {
sources = LWIP_PORTING_FILES + LWIPNOAPPSFILES -
[ "$LWIPDIR/api/sockets.c" ] + [ "porting/src/ethernetif.c" ] --- Add the ethernetif.c file to adapt to the initialization of the Ethernet adapter.
defines = [ "LITEOS_LWIP=1" ]
defines += [ "CHECKSUM_BY_HARDWARE=1" ]
}
config("public") {
defines = [ "_BSD_SOURCE=1" ]
include_dirs =
[ "porting/include" ] + LWIP_PORTING_INCLUDE_DIRS + LWIP_INCLUDE_DIRS
}
```
In the `//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/porting/include/lwip/lwipopts.h` file, retain the original `lwip` configuration, on which the software bus depends, and add the following hardware adaptation options:
```
#ifndef _PORTING_LWIPOPTS_H_
#define _PORTING_LWIPOPTS_H_
#include_next "lwip/lwipopts.h" --- Retain the original configuration.
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_CHECKSUM_ON_COPY 0
#define CHECKSUM_GEN_UDP 0 --- Add hardware adaptation options.
#endif /* _PORTING_LWIPOPTS_H_ */
```
In the `//device/soc/bestechnic/bes2600/liteos_m/components/net/lwip-2.1/porting/src/ethernetif.c` file, add the adaptation to the initialization of the Ethernet adapter as follows:
```
err_t
ethernetif_init(struct netif *netif)
{
...
#ifdef CHECKSUM_BY_HARDWARE
eth_hw_checksum_init();
#endif
...
netif->linkoutput = low_level_output;
netif->drv_send = liteos_low_level_output;
netif->hwaddr_len = NETIF_MAX_HWADDR_LEN;
low_level_init(netif);
driverif_init(netif);
return ERR_OK;
...
}
```
##### dsoftbus Component Adaptation
Add the `dsoftbus` component to the `config.json` file as follows:
```
{
"component": "dsoftbus",
"features": [
"softbus_adapter_config = \"//vendor/bestechnic/mini_distributed_music_player/dsoftbus_lite_config\""
]
},
```
The `dsoftbus` component provides the `softbus_adapter_config` configuration option in the `//foundation/communication/dsoftbus/dsoftbus.gni` file for configuration during porting. The configuration specifies the path for DSoftBus porting adaptation.
In this example, `softbus_adapter_config` is set to `//vendor/bestechnic/mini_distributed_music_player/dsoftbus_lite_config`. The structure of this path is as follows:
```
.
├── feature_config --- DSoftBus configuration, for example, whether to enable self-discovery.
│   └── mini
│   └── config.gni
└── spec_config --- DSoftBus configuration, for example, the DSoftBus log level.
├── softbus_config_adapter.c
├── softbus_config_adapter.h
└── softbus_config_type.h
```
The following configuration items are defined in the `config.gni` file:
| Item | Description |
| ------------------------------------------ | ------------------------ |
| dsoftbus_standard_feature_disc_ble | Whether to enable BLE discovery. |
| dsoftbus_standard_feature_disc_coap | Whether to enable CoAP discovery. |
| dsoftbus_standard_feature_conn_tcp | Whether to enable TCP connection. |
| dsoftbus_standard_feature_conn_br | Whether to enable BR connection. |
| dsoftbus_standard_feature_conn_ble | Whether to enable BLE connection. |
| dsoftbus_standard_feature_conn_p2p | Whether to enable P2P connection. |
| dsoftbus_standard_feature_trans_udp | Whether to enable UDP transmission. |
| dsoftbus_standard_feature_trans_udp_stream | Whether to enable the UDP transport stream. |
| dsoftbus_standard_feature_trans_udp_file | Whether to enable UDP file transfer. |
| dsoftbus_standard_feature_ip_auth | Whether to enable transmission channel authentication.|
| dsoftbus_standard_feature_auth_account | Whether to enable account-based authentication.|
| dsoftbus_standard_feature_qos | Whether to enable QoS. |
The following configuration items are defined in the `softbus_config_adapter.c` file:
| Item | Description |
| ------------------------------------ | ----------------------------- |
| SOFTBUS_INT_MAX_BYTES_LENGTH | SendBytes: maximum number of bytes that can be sent. |
| SOFTBUS_INT_MAX_MESSAGE_LENGTH | SendMessage: maximum length of a message that can be sent.|
| SOFTBUS_INT_CONN_BR_MAX_DATA_LENGTH | Maximum volume of data received over Bluetooth. |
| SOFTBUS_INT_CONN_RFCOM_SEND_MAX_LEN | Maximum volume of data sent over Bluetooth. |
| SOFTBUS_INT_ADAPTER_LOG_LEVEL | Log level. |
| SOFTBUS_STR_STORAGE_DIRECTORY | Storage directory. |
After DSoftBus is configured, it is not started by default. Therefore, you need to invoke the `InitSoftBusServer` function through the startup framework as follows:
```
static void DSoftBus(void)
{
osThreadAttr_t attr;
attr.name = "dsoftbus task";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 65536;
attr.priority = 24;
extern void InitSoftBusServer(void);
if (osThreadNew((osThreadFunc_t) InitSoftBusServer, NULL, &attr) == NULL) {
printf("Falied to create WifiSTATask!\n");
}
}
APP_FEATURE_INIT(DSoftBus);
```
##### RPC Component Adaptation
Add the following `rpc` configuration to the `config.json` file:
```
{
"component": "rpc"
},
```
Similarly, for the `rpc` component, you need to invoke the `StartDBinderService` function through the startup framework. The running of this function depends on the `IP` address obtained by the host. Therefore, invoke this function in the callback of the IP address change event registered by the lwIP protocol stack as follows:
```
static void RpcServerWifiDHCPSucCB(struct netif *netif, netif_nsc_reason_t reason,
const netif_ext_callback_args_t *args)
{
(void) args;
if (netif == NULL) {
printf("%s %d, error: input netif is NULL!\n", __FUNCTION__, __LINE__);
return;
}
if (reason == LWIP_NSC_IPSTATUS_CHANGE) {
if (netif_is_up(netif) && !ip_addr_isany(&netif->ip_addr)) {
printf("%s %d, start rpc server!\n", __FUNCTION__, __LINE__);
StartDBinderService();
}
}
}
static void WifiDHCPRpcServerCB(void)
{
NETIF_DECLARE_EXT_CALLBACK(WifiReadyRpcServerCallback);
netif_add_ext_callback(&WifiReadyRpcServerCallback, RpcServerWifiDHCPSucCB);
}
APP_FEATURE_INIT(WifiDHCPRpcServerCB);
```
#### Startup Subsystem Adaptation
For the `startup` subsystem, adapt the `bootstrap_lite` and `syspara_lite` components. Add the corresponding configuration items to the `vendor/bestechnic_bak/display_demo/config.json` file, as shown below:
```
{
"subsystem": "startup",
"components": [
{
"component": "bootstrap_lite" --- bootstrap_lite component
},
{
"component": "syspara_lite", --- syspara_lite component
"features": [
"enable_ohos_startup_syspara_lite_use_posix_file_api = true"
]
}
]
},
```
When adapting the `bootstrap_lite` component, you need to add the following code snippet to the `//device/soc/bestechnic/bes2600/liteos_m/sdk/bsp/out/best2600w_liteos/_best2001.lds` file:
```
__zinitcall_bsp_start = .;
KEEP (*(.zinitcall.bsp0.init))
KEEP (*(.zinitcall.bsp1.init))
KEEP (*(.zinitcall.bsp2.init))
KEEP (*(.zinitcall.bsp3.init))
KEEP (*(.zinitcall.bsp4.init))
__zinitcall_bsp_end = .;
__zinitcall_device_start = .;
KEEP (*(.zinitcall.device0.init))
KEEP (*(.zinitcall.device1.init))
KEEP (*(.zinitcall.device2.init))
KEEP (*(.zinitcall.device3.init))
KEEP (*(.zinitcall.device4.init))
__zinitcall_device_end = .;
__zinitcall_core_start = .;
KEEP (*(.zinitcall.core0.init))
KEEP (*(.zinitcall.core1.init))
KEEP (*(.zinitcall.core2.init))
KEEP (*(.zinitcall.core3.init))
KEEP (*(.zinitcall.core4.init))
__zinitcall_core_end = .;
__zinitcall_sys_service_start = .;
KEEP (*(.zinitcall.sys.service0.init))
KEEP (*(.zinitcall.sys.service1.init))
KEEP (*(.zinitcall.sys.service2.init))
KEEP (*(.zinitcall.sys.service3.init))
KEEP (*(.zinitcall.sys.service4.init))
__zinitcall_sys_service_end = .;
__zinitcall_sys_feature_start = .;
KEEP (*(.zinitcall.sys.feature0.init))
KEEP (*(.zinitcall.sys.feature1.init))
KEEP (*(.zinitcall.sys.feature2.init))
KEEP (*(.zinitcall.sys.feature3.init))
KEEP (*(.zinitcall.sys.feature4.init))
__zinitcall_sys_feature_end = .;
__zinitcall_run_start = .;
KEEP (*(.zinitcall.run0.init))
KEEP (*(.zinitcall.run1.init))
KEEP (*(.zinitcall.run2.init))
KEEP (*(.zinitcall.run3.init))
KEEP (*(.zinitcall.run4.init))
__zinitcall_run_end = .;
__zinitcall_app_service_start = .;
KEEP (*(.zinitcall.app.service0.init))
KEEP (*(.zinitcall.app.service1.init))
KEEP (*(.zinitcall.app.service2.init))
KEEP (*(.zinitcall.app.service3.init))
KEEP (*(.zinitcall.app.service4.init))
__zinitcall_app_service_end = .;
__zinitcall_app_feature_start = .;
KEEP (*(.zinitcall.app.feature0.init))
KEEP (*(.zinitcall.app.feature1.init))
KEEP (*(.zinitcall.app.feature2.init))
KEEP (*(.zinitcall.app.feature3.init))
KEEP (*(.zinitcall.app.feature4.init))
__zinitcall_app_feature_end = .;
__zinitcall_test_start = .;
KEEP (*(.zinitcall.test0.init))
KEEP (*(.zinitcall.test1.init))
KEEP (*(.zinitcall.test2.init))
KEEP (*(.zinitcall.test3.init))
KEEP (*(.zinitcall.test4.init))
__zinitcall_test_end = .;
__zinitcall_exit_start = .;
KEEP (*(.zinitcall.exit0.init))
KEEP (*(.zinitcall.exit1.init))
KEEP (*(.zinitcall.exit2.init))
KEEP (*(.zinitcall.exit3.init))
KEEP (*(.zinitcall.exit4.init))
__zinitcall_exit_end = .;
```
The added code snippet is for storing the external APIs provided by `bootstrap_init`, which are injected. For details about the APIs, see `//utils/native/lite/include/ohos_init.h`. The following table lists the main macros for automatic service initialization.
| API | Description |
| ---------------------- | -------------------------------- |
| SYS_SERVICE_INIT(func) | Entry for initializing and starting a core system service.|
| SYS_FEATURE_INIT(func) | Entry for initializing and starting a core system feature.|
| APP_SERVICE_INIT(func) | Entry for initializing and starting an application-layer service. |
| APP_FEATURE_INIT(func) | Entry for initializing and starting an application-layer feature. |
![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
You need to add a forcible link to the` lib` file generated by building the previous loaded components.
​ If the `bootstrap_lite` component is configured in the `vendor/bestechnic/display_demo/config.json` file, as shown below:
```
{
"subsystem": "startup",
"components": [
{
"component": "bootstrap_lite"
},
...
]
},
```
​ The `bootstrap_lite` component will compile the `//base/startup/bootstrap_lite/services/source/bootstrap_service.c` file. In this file, inject the `Init` function symbol to `__zinitcall_sys_service_start` and `__zinitcall_sys_service_end` through `SYS_SERVICE_INIT`. Because the `Init` function is not explicitly called, it needs to be forcibly linked to the final image. The sample code is as follows:
```
static void Init(void)
{
static Bootstrap bootstrap;
bootstrap.GetName = GetName;
bootstrap.Initialize = Initialize;
bootstrap.MessageHandle = MessageHandle;
bootstrap.GetTaskConfig = GetTaskConfig;
bootstrap.flag = FALSE;
SAMGR_GetInstance()->RegisterService((Service *)&bootstrap);
}
SYS_SERVICE_INIT(Init); --- Once SYS (SYS_INIT) is started, the generated library needs to be forcibly linked.
```
​ In the `//base/startup/bootstrap_lite/services/source/BUILD.gn` file, the save path of `libbootstrap.a` is set to `out/v200zr/display_demo/libs` as follows:
```
static_library("bootstrap") {
sources = [
"bootstrap_service.c",
"system_init.c",
]
....
```
​ In this case, you need to add `bootstrap` under `force_link_libs` in `vendor/bestechnic/display_demo/config.json`, as shown below:
```
"bin_list": [
{
"elf_name": "wifiiot",
"bsp_target_name": "best2600w_liteos",
"signature": "false",
"burn_name": "rtos_main",
"enable": "true",
"force_link_libs": [
"bootstrap", --- Forcibly link to libbootstrap.a.
...
]
},
```
When the `syspara_lite` component is adapted, system parameters are written to a file for persistent storage. In the mini system, file operation APIs include `POSIX` and `HalFiles`.
For access to the file system in the kernel, use the `POSIX` API, which means you need to add `enable_ohos_startup_syspara_lite_use_posix_file_api = true` to the `features` field.
If you are using the `HalFiles` API, no modification is required.
During adaptation of the `GetSerial` API, no `Serial Number` is written to the development board, which is different from the case in the production line. Therefore, you need to assign an attribute to uniquely identify the development board. In this example, the Wi-Fi MAC address is used.
```
#define ETH_ALEN 6
#define MAC_BITS 4
#define MAC_HIGH_MASK 0xf0
#define MAC_LOW_MASK 0x0f
#define HEX_A 0xa
#define CHAR_NUM_OFFSET 0x30
#define CHAR_CAPITAL_OFFSET 0x37
#define STR_END_FLAG '\0'
typedef unsigned char u8;
static char serialNumber[2*ETH_ALEN + 1]; --- The last character is used as the end character '\0'.
static char Hex2Char(u8 hex)
{
if (hex < HEX_A) {
return hex + CHAR_NUM_OFFSET; --- Convert the value 0 to char '0'.
} else {
return hex + CHAR_CAPITAL_OFFSET; --- Convert the value 0xa to char 'A'.
}
}
const char* HalGetSerial(void)
{
char macAddr[ETH_ALEN];
// as devboard has no production serial number, we just
// use wifi mac address as device serial number.
if (serialNumber[0] == STR_END_FLAG) { --- The MAC address is obtained only when the API is invoked for the first time.
extern int bwifi_get_own_mac(u8 *addr);
bwifi_get_own_mac(macAddr); --- Obtain the MAC address.
int j = 0;
for (int i = 0; i < ETH_ALEN; i++) {
u8 lowFour, highFour;
highFour = (macAddr[i] & MAC_HIGH_MASK) >> MAC_BITS;
serialNumber[j] = Hex2Char(highFour);
j++;
lowFour = macAddr[i] & MAC_LOW_MASK;
serialNumber[j] = Hex2Char(lowFour);
j++;
} --- Convert the MAC address to the serial number.
}
return serialNumber;
}
```
#### DFX Subsystem Adaptation
To adapt the DFX subsystem, you need to add the `hilog_lite` component in the `config.json` file.
```
{
"subsystem": "hiviewdfx",
"components": [
{
"component": "hilog_lite",
"optional": "true"
}
]
},
```
Register the log output implementation function in `//device/soc/bestechnic/bes2600/liteos_m/components/utils/src/hm_sys.c`.
```
boolean HilogProc_Impl(const HiLogContent *hilogContent, uint32 len)
{
char tempOutStr[LOG_FMT_MAX_LEN] = {0};
if (LogContentFmt(tempOutStr, sizeof(tempOutStr), hilogContent) > 0) {
printf(tempOutStr);
}
return TRUE;
}
HiviewRegisterHilogProc(HilogProc_Impl);
```
#### distributedschedule Subsystem Adaptation
To adapt the `distributedschedule` subsystem, you need to add the `samgr_lite` component in the `config.json` file, as shown below:
```
{
"subsystem": "distributedschedule",
"components": [
{
"component": "samgr_lite",
"features": [
"config_ohos_distributedschedule_samgr_lite_shared_task_size = 4096"
]
}
]
},
```
In the mini system, the default size of the shared task stack for `samgr_lite` is `0x800`. To avoid stack overflow, adjust the size to `0x1000`.
#### Security Subsystem Adaptation
To adapt the `security` subsystem, you need to add the `huks/deviceauth_lite` component in the `config.json` file, as shown below:
```
{
"subsystem": "security",
"components": [
{
"component": "huks",
"features": [
"huks_use_lite_storage = true",
"huks_use_hardware_root_key = true",
"huks_config_file = \"hks_config_lite.h\"",
"huks_key_store_path = \"/data/\"",
"ohos_security_huks_mbedtls_porting_path = \"//device/soc/bestechnic/hals/mbedtls\""
]
},
{
"component": "deviceauth_lite",
"features": [
"deviceauth_storage_path = \"/data/\"",
"deviceauth_hichain_thread_stack_size = 9472"
]
}
]
}
```
During `huks` component adaptation, set `huks_key_store_path` to the path for storing the key and `ohos_security_huks_mbedtls_porting_path` to the directory for `mbedtls` adaptation, so that the chip can adapt `mbedtls` to hardware random numbers.
During `deviceauth_lite` component adaptation, set `deviceauth_storage_path` to the path for storing device authentication information and `deviceauth_hichain_thread_stack_size` to the thread stack size.
#### Multimedia Subsystem Adaptation
To adapt the multimedia subsystem, you need to add the `histreamer` component in the `config.json` file, as shown below:
```
{
"subsystem": "multimedia",
"components": [
{
"component": "histreamer",
"features": [
"multimedia_histreamer_enable_plugin_hdi_adapter = true",
"multimedia_histreamer_enable_plugin_minimp3_adapter = true",
"multimedia_histreamer_enable_plugin_ffmpeg_adapter = false",
"config_ohos_multimedia_histreamer_stack_size = 65536"
]
}
]
},
```
The configuration items of the `histreamer` component are described as follows:
| Item | Description |
| --------------------------------------------------- | ------------------------------- |
| multimedia_histreamer_enable_plugin_hdi_adapter | Whether to enable histreamer to connect to the HDMI interface.|
| multimedia_histreamer_enable_plugin_minimp3_adapter | Whether to enable the plug-in to adapt to miniMP3. |
| multimedia_histreamer_enable_plugin_ffmpeg_adapter | Whether to enable the plug-in to adapt to FFmpeg. |
| config_ohos_multimedia_histreamer_stack_size | Size of the histreamer stack. |
#### utils Subsystem Adaptation
To adapt the `utils` subsystem, you need to add the `kv_store`, `js_builtin`, `timer_task`, and `kal_timer` components in the `config.json` file, as shown below:
```
{
"subsystem": "utils",
"components": [
{
"component": "kv_store",
"features": [
"enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true"
]
},
{
"component": "js_builtin"
},
{
"component": "timer_task"
},
{
"component": "kal_timer",
}
]
},
```
Similar to that in the `syspara_lite` component, the key-value pair is written to a file during adaptation of the `kv_store` component. In the mini system, file operation APIs include `POSIX` and `HalFiles`. For access to the file system in the kernel, use the `POSIX` API, which means that you need to add `enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = true` to the `features` field. If you are using the `HalFiles` API, no modification is required.
#### Graphics Subsystem Adaptation
To adapt the `graphic` subsystem, you need to add the `graphic_utils` component in the `config.json` file, as shown below:
```
"components": [
{
"component": "graphic_utils",
"features": [
"enable_ohos_graphic_utils_product_config = true"
]
},
{
"component": "ui"
}
]
}
```
For details about `graphic` configuration, see `//vendor/bestechnic/display_demo/graphic_config/product_graphic_lite_config.h`.
For details about `graphic` adaptation, see `//device/soc/bestechnic/bes2600/liteos_m/components/ui`, . The main functions are as follows:
- `display_device`: instantiates `BaseGfxEngine`.
- `touch_input`: instantiates `PointerInputDevice`.
- `UiMainTask`: initializes the font engine and executes rendering tasks.
Layers of the `graphic` subsystem:
```
aafwk_lite + appexecfwk_lite (AAFWK + APPEXECFWK)
|
ace_engine_lite + jerryscript + i18n_lite + resmgr_lite + utils/native/lite/... (ACE and JS engines and their dependencies)
|
graphic_ui + graphic_utils (Graphic framework)
|
giflib + libjpeg + libpng + qrcodegen + freetype... (Third-party graphics library)
```
For details about the graphic application demo, see the `//vendor/bestechnic/display_demo/tests/app.cpp` file, as shown below:
```
/* ui app entry */
void RunApp()
{
#ifdef UI_TEST
AnimatorDemoStart(); --- native ui demo
#elif defined(ABILITY_TEST)
StartJSApp(); --- js demo
#endif
}
void AppEntry(void)
{
UiMain();
}
APP_FEATURE_INIT(AppEntry);
```
#### ACE Subsystem Adaptation
To adapt the ACE subsystem, you need to add the `ace_engine_lite` component in the `config.json` file, as shown below:
{
"subsystem": "ace",
"components": [
{
"component": "ace_engine_lite",
"features": [
"enable_ohos_ace_engine_lite_product_config = true"
]
}
]
},
For details about the `ace_engine_lite` configuration, see `//vendor/bestechnic/display_demo/ace_lite_config/product_acelite_config.h`.
The `ace_lite` application is developed in JavaScript. The detailed procedure is as follows:
1. Use DevEco Studio to compile a JavaScript application. For details, see [Lite Wearable Development Specifications](https://developer.harmonyos.com/en/docs/documentation/doc-references/lite-wearable-file-0000001176751380).
2. Use the Previewer feature to preview the application and obtain the JS package `entry\.preview\intermediates\res\debug\lite\assets\js\default`.
3. Place the JS package to the corresponding file system path `vendor/bestechnic/display_demo/fs/data/data/js`, as shown below:
```
├── app.js
├── common
├── i18n
├── manifest.json
└── pages
```
4. Start building to generate the system image. Burn the system image the development board, and the system will load and start the `ace` application from `app.js`.
#### aafwk Subsystem Adaptation
To adapt the `aafwk` subsystem, you need to add the `aafwk_lite` component in the `config.json` file, as shown below:
```
{
"subsystem": "aafwk",
"components": [
{
"component": "aafwk_lite",
"features": [
"enable_ohos_appexecfwk_feature_ability = true", --- Enable the FA to support the graphics capability.
"config_ohos_aafwk_ams_task_size = 4096" --- Configure the size of the aafwk stack.
]
}
]
},
```
For details about the `aafwk_lite` use cases, see the `vendor/bestechnic/display_demo/tests/ability` directory, which includes the `launcher` and `js app` applications. The function invocation process of the applications is described as follows:
1. `launcher` application: Use `InstallLauncher` to install the `native ui` application, whose `BundleName` is `"com.example.launcher"`. After `AbilityMgrSliteFeature` is started, `AbilityMgrHandler::StartLauncher()` is invoked to start the `launcher` application.
2. `StartJSApp` application: Use `StartAbility` to start any `Want` and pass `want data` to `JS_APP_PATH`,
`SetWantData(&want, JS_APP_PATH, strlen(JS_APP_PATH) + 1)`.
#### appexecfwk Subsystem Adaptation
To adapt the `appexecfwk` subsystem, you need to add the `appexecfwk_lite` component in the `config.json` file, as shown below:
```
{
"subsystem": "appexecfwk",
"components": [
{
"component": "appexecfwk_lite"
}
]
},
```
## Compatibility Test
### Product Compatibility Specifications
For details about product compatibility specifications, see [Introduction to Product Compatibility SIG](https://gitee.com/openharmony-sig/compatibility/tree/master).
### XTS Test Cases
For details about the `XTS` test cases, see [XTS](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-xts-guide.md). To adapt the `XTS` subsystem, you need to add the `xts_acts`/`xts_tools` component in the `config.json` file, as shown below:
{
"subsystem": "xts",
"components": [
{ "component": "xts_acts", "features":
[
"config_ohos_xts_acts_utils_lite_kv_store_data_path = \"/data\"",
"enable_ohos_test_xts_acts_use_thirdparty_lwip = true"
]
},
{ "component": "xts_tools", "features":[] }
]
}
Where:
- `config_ohos_xts_acts_utils_lite_kv_store_data_path` is the name of the root directory to which the file system is mounted.
- `enable_ohos_test_xts_acts_use_thirdparty_lwip` indicates whether to use the source code in the `thirdparty/lwip` directory. The value `true` means to use the source code in the `thirdparty/lwip` directory, and `false` means the opposite.
After the execution is complete, `xx Tests xx Failures xx Ignored` is displayed, as shown below:
```
...
[16:53:43:438]../../../test/xts/acts/utils_lite/kv_store_hal/src/kvstore_func_test.c:793:testKvStoreMaxSize004:PASS
[16:53:43:438]+-------------------------------------------+
[16:53:43:438]
[16:53:43:438]-----------------------
[16:53:43:438]32 Tests 0 Failures 0 Ignored
[16:53:43:438]OK
[16:53:43:439]All the test suites finished!
```
### Report Submission
Save the preceding `XTS` test result as a test report and upload it to the OpenHarmony compatibility test website. This is a prerequisite for synchronizing the code from the `sig` repository to the `master` repository. The procedure is as follows:
Step 1: Compress the `XTS` test report into a `zip` file.
Step 2: Generate the SHA checksum of the test report. In this example, the SHA checksum is generated by uploading the `zip` file to the [SHA checksum online generator](https://tool.lmeee.com/jiami/filehash).
Step 3: Go to the `OpenHarmony` [compatibility test website](https://www.openharmony.cn/old/#/Compatibility_test) and upload the report.
- Set `API Level` to the `"sdkApiLevel"` value in the report.
- Set `OS` to the `"OS Version"` value in the report.
## Coming Soon
The following aspects will be added in the future:
- Bluetooth
- `bms` package installation
- Verifying `bytecode` for running `JS`
- Distributed capabilities: `dms` and `dm`
- Example of a distributed music player
# Mini System SoC Porting Cases
- **[Mini-System Devices with Screens — Bestechnic SoC Porting Case](porting-bes2600w-on-minisystem-display-demo.md)**
- **[Combo Solution – ASR Chip Porting Case](porting-asr582x-combo-demo.md)**
# Porting<a name="EN-US_TOPIC_0000001157479393"></a> # Porting<a name="EN-US_TOPIC_0000001157479393"></a>
- **[Third-Party Library Porting Guide](porting-thirdparty.md)**
- **[Mini System SoC Porting Guide](porting-minichip.md)** - **[Mini System SoC Porting Guide](porting-minichip.md)**
- **[Small System SoC Porting Guide](porting-smallchip.md)** - **[Small System SoC Porting Guide](porting-smallchip.md)**
- **[Standard System Porting Guide](standard-system-porting-guide.md)**
- **[Standard System Porting Guide](standard-system-porting-guide.md)** - **[Third-Party Library Porting Guide for Mini and Small Systems](porting-thirdparty.md)**
# Getting Started # Getting Started
- Getting Started for Mini and Small Systems
- [Mini and Small Systems](quickstart-lite.md) - [Mini and Small System Overview](quickstart-ide-lite-overview.md)
- [Overview](quickstart-lite-overview.md) - Environment Preparation
- [Introduction](quickstart-lite-introduction.md) - [Setting Up the Windows+Ubuntu Hybrid Build Environment](quickstart-ide-lite-env-setup-win-ubuntu.md)
- [Hi3861 Development Board](quickstart-lite-introduction-hi3861.md) - [Obtaining Source Code](quickstart-ide-lite-sourcecode-acquire.md)
- [Hi3516 Development Board](quickstart-lite-introduction-hi3516.md) - [Creating a Source Code Project](quickstart-ide-lite-create-project.md)
- [Hi3518 Development Board](quickstart-lite-introduction-hi3518.md) - Running a Hello World Program
- [Environment Setup](quickstart-lite-env-setup.md) - Hi3861 Development Board
- [Overview](quickstart-lite-env-setup-overview.md) - [Writing a Hello World Program](quickstart-ide-lite-steps-hi3861-application-framework.md)
- [Setting Up Windows Development Environment](quickstart-lite-env-setup-windows.md) - [Building](quickstart-ide-lite-steps-hi3861-building.md)
- [Setting Up Ubuntu Development Environment](quickstart-lite-env-setup-linux.md) - [Burning](quickstart-ide-lite-steps-hi3861-burn.md)
- [FAQs](quickstart-lite-env-setup-faqs.md) - [Networking](quickstart-ide-lite-steps-hi3861-netconfig.md)
- [How to Develop](quickstart-lite-steps.md) - [Debugging and Verification](quickstart-ide-lite-steps-hi3861-debug.md)
- [Hi3861](quickstart-lite-steps-hi3861.md) - [Running](quickstart-ide-lite-steps-hi3816-running.md)
- [Setting Up the Environment](quickstart-lite-steps-hi3861-setting.md) - Hi3516 Development Board
- [Setting Up WLAN Connection](quickstart-lite-steps-hi3861-connection.md) - [Writing a Hello World Program](quickstart-ide-lite-steps-hi3516-application-framework.md)
- [Running a Hello World Program](quickstart-lite-steps-hi3861-running.md) - [Building](quickstart-ide-lite-steps-hi3516-building.md)
- [FAQs](quickstart-lite-steps-hi3861-faqs.md) - [Burning](quickstart-ide-lite-steps-hi3516-burn.md)
- [Hi3516](quickstart-lite-steps-hi3516.md) - [Running](quickstart-ide-lite-steps-hi3516-running.md)
- [Setting Up the Environment](quickstart-lite-steps-hi3516-setting.md) - Appendix
- [Running a Hello OHOS Program](quickstart-lite-steps-hi3516-running.md) - Introduction to Development Boards
- [Developing a Driver](quickstart-lite-steps-hi3516-program.md) - [Introduction to the Hi3861 Development Board](quickstart-ide-lite-introduction-hi3861.md)
- [FAQs](quickstart-lite-steps-hi3516-faqs.md) - [Introduction to the Hi3516 Development Board](quickstart-ide-lite-introduction-hi3516.md)
- [Hi3518](quickstart-lite-steps-hi3518.md) - [Getting Started with Mini and Small Systems (Installation Package Mode)](quickstart-lite-package-directory.md)
- [Setting Up the Environment](quickstart-lite-steps-hi3518-setting.md) - Getting Started for Standard System
- [Running a Hello OHOS Program](quickstart-lite-steps-hi3518-running.md) - [Standard System Overview](quickstart-ide-standard-overview.md)
- [FAQs](quickstart-lite-steps-hi3518-faqs.md) - Environment Preparation
- [Standard System](quickstart-standard.md) - [Setting Up the Windows+Ubuntu Hybrid Build Environment](quickstart-ide-standard-env-setup-win-ubuntu.md)
- [Introduction](quickstart-standard-overview.md) - [Obtaining Source Code](quickstart-ide-standard-sourcecode-acquire.md)
- [Setting Up Windows Development Environment](quickstart-standard-windows-environment.md) - [Creating a Source Code Project](quickstart-ide-standard-create-project.md)
- [Setting Up Ubuntu Development Environment in Docker Mode](quickstart-standard-docker-environment.md) - Running a Hello World Program
- [Setting Up Ubuntu Development Environment with Installation Package](quickstart-standard-package-environment.md) - Hi3516 Development Board
- [Burning Images](quickstart-standard-burn.md) - [Writing a Hello World Program](quickstart-ide-standard-running-hi3516-create.md)
- [Running an Image](quickstart-standard-running.md) - [Building](quickstart-ide-standard-running-hi3516-build.md)
- [FAQs](quickstart-standard-faqs.md) - [Burning](quickstart-ide-standard-running-hi3516-burning.md)
\ No newline at end of file - [Running](quickstart-ide-standard-running-hi3516-running.md)
- RK3568 Development Board
- [Writing a Hello World Program](quickstart-ide-standard-running-rk3568-create.md)
- [Building](quickstart-ide-standard-running-rk3568-build.md)
- [Burning](quickstart-ide-standard-running-rk3568-burning.md)
- [Running](quickstart-ide-standard-running-rk3568-running.md)
- Appendix
- Introduction to Development Boards
- [Introduction to the Hi3516 Development Board](quickstart-ide-standard-board-introduction-hi3516.md)
- [Introduction to the RK3568 Development Board](quickstart-ide-standard-board-introduction-rk3568.md)
- [Getting Started for Standard System (Installation Package Mode)](quickstart-standard-package-directory.md)
# Getting Started with Mini and Small Systems (Installation Package Mode)
- **[Mini and Small System Overview](quickstart-lite-overview.md)**
- **[Environment Preparation](quickstart-lite-env-setup.md)**
- **[Running a Hello World Program](quickstart-lite-steps.md)**
- **[FAQs](quickstart-lite-env-setup-faqs.md)**
- **[Appendix](quickstart-lite-appendix.md)**
# Appendix
- **[Introduction to Development Boards](quickstart-ide-lite-board-introduction.md)**
# Introduction to Development Boards
- **[Introduction to the Hi3861 Development Board](quickstart-ide-lite-introduction-hi3861.md)**
- **[Introduction to the Hi3516 Development Board](quickstart-ide-lite-introduction-hi3516.md)**
# Creating a Source Code Project
After [setting up the Windows+Ubuntu hybrid development environment](../quick-start/quickstart-ide-lite-env-setup-win-ubuntu.md) and [obtaining source code](../quick-start/quickstart-ide-lite-sourcecode-acquire.md), perform the following steps to create a source code project in Windows:
1. Open DevEco Device Tool, go to the home page, and click **Import Project** to open your project or source code.
![en-us_image_0000001171426014](figures/en-us_image_0000001171426014.png)
2. Select the source code directory to be imported and click **Import**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Make sure the selected directory does not contain Chinese characters or spaces. Otherwise, the building may fail.
![en-us_image_0000001271477045](figures/en-us_image_0000001271477045.png)
3. If you select to open the OpenHarmony source code, a message will be displayed indicating that the project is not a DevEco Device Tool project. Click **Import** to continue.
![en-us_image_0000001135394334](figures/en-us_image_0000001135394334.png)
4. On the **Select Project type** page, select **Import from OpenHarmony Source**.
![en-us_image_0000001215743910](figures/en-us_image_0000001215743910.png)
5. On the **Import Project** page, select a product, and the MCU, board, company, and kernel fields will be automatically populated. Then, select the OpenHarmony source code version for **ohosVersion**. The following figure uses **wifiiot_hispark_pegasus** as an example.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - Set **Product** to **wifiiot_hispark_pegasus** for the Hi3861 development board.
>
> - Set **Product** to **ipcamera_hispark_taurus** for the Hi3516D V300 development board.
![en-us_image_0000001271237241](figures/en-us_image_0000001271237241.png)
6. Click **Open** to open the project or source code.
# Setting Up the Windows+Ubuntu Hybrid Development Environment
In embedded development, Windows-based tools, such as Visual Studio Code, are widely used in code editing. Yet, as the source code of most development boards, such as Hi3861 and Hi3516, cannot be built in Windows, these development boards require the Ubuntu build environment.
In the Windows+Ubuntu hybrid build environment, you can enjoy the benefits of both DevEco Device Tool for Windows and DevEco Device Tool for Ubuntu (where Visual Studio Code is optional).
## System Requirements
- Windows: Windows 10 (64-bit)
- Ubuntu: Ubuntu 20.04 or later; recommended memory: 16 GB or higher.
- User name: cannot contain Chinese characters
- DevEco Device Tool: 3.0 Release
## Setting Up the Ubuntu Build Environment
The setup procedure varies, depending on whether you need a GUI. If you need a GUI, you need to install Visual Studio Code. In this case, follow the instructions in [Setting Up the Ubuntu Development Environment](https://device.harmonyos.com/en/docs/documentation/guide/ide-install-ubuntu-0000001072959308). If you do not need a GUI, perform the steps below:
1. Make sure the Ubuntu shell environment is **bash**.
1. Run the following command and check whether the command output is **bash**. If the command output is not **bash**, go to step 2.
```
ls -l /bin/sh
```
![en-us_image_0000001226764302](figures/en-us_image_0000001226764302.png)
2. Start the command-line tool, run the following command, enter your password, and select **No** to set **Ubuntu shell** to **bash**.
```
sudo dpkg-reconfigure dash
```
![en-us_image_0000001243641075](figures/en-us_image_0000001243641075.png)
2. Download the [DevEco Device Tool 3.0 Release Linux version](https://device.harmonyos.com/cn/ide#download).
3. Decompress the DevEco Device Tool software package and assign permission on the folder obtained from the decompression.
1. Go to the directory where the DevEco Device Tool software package is stored and run the following command to decompress the software package. In the command, change **devicetool-linux-tool-3.0.0.400.zip** to the actual software package name.
```
unzip devicetool-linux-tool-3.0.0.400.zip
```
2. Open the folder of the decompressed software package and run the following command to grant the execute permission on the installation file. In the command, change **devicetool-linux-tool-3.0.0.400.sh** to the actual installation file name.
```
chmod u+x devicetool-linux-tool-3.0.0.400.sh
```
4. Run the following command to install DevEco Device Tool, where **devicetool-linux-tool-3.0.0.400.sh** indicates the installation file name.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> During the installation, the setup wizard automatically checks whether Python 3.8 or 3.9 is installed. If Python 3.8 or 3.9 is not installed, the setup wizard displays the "Do you want to continue?" message; enter **Y** to allow the setup wizard to automatically install Python.
```
sudo ./devicetool-linux-tool-3.0.0.400.sh
```
Wait until the "Deveco Device Tool successfully installed." message is displayed.
![en-us_image_0000001198722374](figures/en-us_image_0000001198722374.png)
## Setting Up Windows Development Environment
To remotely access the Ubuntu environment through Windows and enjoy the benefits of DevEco Device Tool for Windows, you need to install DevEco Device Tool on Windows.
1. Download the [DevEco Device Tool 3.0 Release](https://device.harmonyos.com/cn/ide#download) Windows edition.
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**. You are advised to install DevEco Device Tool in a non-system drive.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If you have installed DevEco Device Tool 3.0 Beta2 or earlier, the earlier version will be uninstalled before you install a new version. If the following error message is displayed during the uninstallation, click **Ignore** to continue the installation. This error does not affect the installation of the new version.
>
> ![en-us_image_0000001239275843](figures/en-us_image_0000001239275843.png)
![en-us_image_0000001270076961](figures/en-us_image_0000001270076961.png)
4. When prompted, select the tools to be automatically installed.
1. On the **VSCode installation confirm** page, select **Install VScode 1.62.2 automatically** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Visual Studio Code 1.62 or later has been installed, this step will be skipped.
![en-us_image_0000001237801283](figures/en-us_image_0000001237801283.png)
2. On the displayed **Python select page**, select **Download from Huawei mirror** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Python 3.8 or 3.9 has been installed, select **Use one of compatible on your PC**.
![en-us_image_0000001193983334](figures/en-us_image_0000001193983334.png)
5. In the dialog box shown below, click **Next** to download and install the tools..
![en-us_image_0000001239634067](figures/en-us_image_0000001239634067.png)
6. Wait for the DevEco Device Tool setup wizard to automatically install DevEco Device Tool. After the installation is complete, click **Finish** to close the setup wizard.
![en-us_image_0000001239650137](figures/en-us_image_0000001239650137.png)
7. From Visual Studio Code, access the DevEco Device Tool page. Now you can conduct your development in DevEco Device Tool.
![en-us_image_0000001225760456](figures/en-us_image_0000001225760456.png)
## Configuring Windows to Remotely Access the Ubuntu Build Environment
### Installing the SSH Service and Obtaining the IP Address for Remote Access
1. In Ubuntu, open the Terminal tool and run the following command to install the SSH service:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the command fails to be executed and the system displays a message indicating that the openssh-server and openssh-client depend on different versions, install the openssh-client of the required version (for example, **sudo apt-get install openssh-client=1:8.2p1-4**) as prompted on the command-line interface (CLI) and run the command again to install the openssh-server.
```
sudo apt-get install openssh-server
```
2. Run the following command to start the SSH service:
```
sudo systemctl start ssh
```
3. Run the following command to obtain the IP address of the current user for remote access to the Ubuntu environment from Windows:
```
ifconfig
```
![en-us_image_0000001215737140](figures/en-us_image_0000001215737140.png)
### Installing Remote SSH
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001239080359](figures/en-us-cn_image_0000001239080359.png), and search for **remote-ssh** in the Extension Marketplace.
![en-us_image_0000001193920448](figures/en-us_image_0000001193920448.png)
2. Click **Install** to install Remote-SSH. After the installation is successful, **Remote-SSH** is displayed on the **INSTALLED** list.
![en-us_image_0000001238880335](figures/en-us_image_0000001238880335.png)
### Remotely Connecting to the Ubuntu Environment
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001238760373](figures/en-us_image_0000001238760373.png), and click + on the **REMOTE EXOPLORER** page.
![en-us_image_0000001215878922](figures/en-us_image_0000001215878922.png)
2. In the **Enter SSH Connection Command** text box, enter **ssh *username@ip_address***, where *ip_address* indicates the IP address of the remote computer to be connected and *username* indicates the account name used for logging in to the remote computer.
![en-us_image_0000001215879750](figures/en-us_image_0000001215879750.png)
3. In the displayed dialog box, select the default first option as the SSH configuration file.
![en-us_image_0000001260519729](figures/en-us_image_0000001260519729.png)
4. Under **SSH TARGETS**, find the remote computer and click ![en-us_image_0000001194080414](figures/en-us_image_0000001194080414.png) to start it.
![en-us_image_0000001215720398](figures/en-us_image_0000001215720398.png)
5. In the displayed dialog box, select **Linux**, select **Continue**, and enter the password for logging in to the remote computer.
![en-us_image_0000001215897530](figures/en-us_image_0000001215897530.png)
After the connection is successful, the plug-in is automatically installed in the .vscode-server folder on the remote computer. After the installation is complete, reload Visual Studio Code in Windows as prompted. Then you can develop, compile, and burn source code in DevEco Device Tool on Windows.
### Registering the Public Key for Accessing the Ubuntu Environment
After the preceding operations are complete, you can remotely connect to the Ubuntu environment through Windows for development. However, you need to frequently enter the remote connection password. To eliminate this need, you can use the SSH public key.
1. Open the Git bash CLI and run the following command to generate an SSH public key. During command execution, perform operations as prompted. Set **username** and **ip** to the user name and IP address you use for connecting to the Ubuntu system.
```
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip
```
![en-us_image_0000001271532317](figures/en-us_image_0000001271532317.png)
2. In Visual Studio Code, click the remote connection setting button and open the **config** file.
![en-us_image_0000001226034634](figures/en-us_image_0000001226034634.png)
3. In the **config** file, add the SSK key file information, as shown below. Then save the file.
![en-us_image_0000001270356233](figures/en-us_image_0000001270356233.png)
# Environment Preparation
- **[Setting Up the Windows+Ubuntu Hybrid Build Environment](quickstart-ide-lite-env-setup-win-ubuntu.md)**
- **[Obtaining Source Code](quickstart-ide-lite-sourcecode-acquire.md)**
# Introduction to the Hi3516 Development Board
## Introduction
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** Hi3516 front view
![en-us_image_0000001271234717](figures/en-us_image_0000001271234717.png)
## Development Board Specifications
**Table 1** Hi3516 specifications
| Item| Description|
| -------- | -------- |
| Processor and internal memory| -&nbsp;Hi3516D V300 chip<br>-&nbsp;DDR3&nbsp;1GB<br>-&nbsp;eMMC 4.5, 8 GB capacity|
| External components| -&nbsp;Ethernet port<br>-&nbsp;Audio and video<br>&nbsp;&nbsp;-&nbsp;1 voice input<br>&nbsp;&nbsp;-&nbsp;1 mono channel (AC_L) output, connected to a 3 W power amplifier (LM4871)<br>&nbsp;&nbsp;-&nbsp;MicroHDMI (1-channel HDMI 1.4)<br>-&nbsp;Camera<br>&nbsp;&nbsp;-&nbsp;Sensor IMX335<br>&nbsp;&nbsp;-&nbsp;M12 lens, 4 mm focal length, and 1.8 aperture<br>-&nbsp;Display<br>&nbsp;&nbsp;-&nbsp;LCD connector (2.35-inch)<br>&nbsp;&nbsp;-&nbsp;LCD connector (5.5-inch)<br>-&nbsp;External components and ports<br>&nbsp;&nbsp;-&nbsp;Memory card port<br>&nbsp;&nbsp;-&nbsp;JTAG/I2S port<br>&nbsp;&nbsp;-&nbsp;ADC port<br>&nbsp;&nbsp;-&nbsp;Steering gear port<br>&nbsp;&nbsp;-&nbsp;Grove connector<br>&nbsp;&nbsp;-&nbsp;USB 2.0 (Type-C)<br>&nbsp;&nbsp;-&nbsp;Three function keys, two user-defined keys, and one upgrade key<br>&nbsp;&nbsp;-&nbsp;LED indicator, green or red|
# Introduction to the Hi3861 Development Board
## Introduction
Hi3861 is a 2 x 5 cm development board. It is a 2.4 GHz WLAN SoC chip that highly integrates the IEEE 802.11b/g/n baseband and radio frequency (RF) circuit. It supports OpenHarmony and provides an open and easy-to-use development and debugging environment.
**Figure 1** Hi3861 development board
![en-us_image_0000001226634692](figures/en-us_image_0000001226634692.png)
The Hi3861 development board can also be connected to the Hi3861 mother board to expand its peripheral capabilities. The following figure shows the Hi3861 mother board.
**Figure 2** Hi3861 mother board
![en-us_image_0000001226794660](figures/en-us_image_0000001226794660.png)
- 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.
- The Hi3861 chip integrates the high-performance 32-bit microprocessor, hardware security engine, and various peripheral interfaces. The peripheral interfaces include the Synchronous Peripheral Interface (SPI), Universal Asynchronous Receiver & Transmitter (UART), the Inter-Integrated Circuit (I2C), Pulse Width Modulation (PWM), General Purpose Input/Output (GPIO) interface, and Analog to Digital Converter (ADC). The Hi3861 chip also supports the high-speed Secure Digital Input/Output (SDIO) 2.0 interface, with a maximum clock frequency of 50 MHz. This chip has a built-in static random access memory (SRAM) and flash memory, so that programs can run independently or run from a flash drive.
- The Hi3861 chip applies to Internet of Things (IoT) devices such as smart home appliances.
**Figure 3** Functional block diagram of Hi3861
![en-us_image_0000001271234729](figures/en-us_image_0000001271234729.png)
## Resources and Constraints
The resources of the Hi3861 development board are limited. The entire board has a 2 MB flash memory and 352 KB RAM. When writing service code, pay attention to the resource usage efficiency.
## Development Board Specifications
**Table 1** Hi3861 specifications
| Item| Description|
| -------- | -------- |
| General specifications| -&nbsp;1 x 1 2.4 GHz frequency band (ch1–ch14)<br>-&nbsp;PHY supports IEEE 802.11b/g/n.<br>-&nbsp;MAC supports IEEE802.11d/e/h/i/k/v/w.<br>-&nbsp;Built-in PA and LNA; integrated TX/RX switch and Balun<br>-&nbsp;Support for STA and AP modes. When functioning as an AP, it supports a maximum of 6 STAs.<br>-&nbsp;Support for WFA WPA/WPA2 personal and WPS2.0.<br>-&nbsp;2/3/4-line PTA solution that coexists with BT/BLE chips.<br>-&nbsp;Input voltage range: 2.3 V to 3.6 V<br>-&nbsp;I/O power voltage: 1.8 V or 3.3 V.<br>-&nbsp;RF self-calibration<br>-&nbsp;Low power consumption:<br>&nbsp;&nbsp;-&nbsp;Ultra Deep Sleep mode: 5 μA@3.3 V<br>&nbsp;&nbsp;-&nbsp;DTIM1: 1.5 mA \@3.3V<br>&nbsp;&nbsp;-&nbsp;DTIM3: 0.8 mA \@3.3V|
| PHY features| -&nbsp;Supports all data rates of the IEEE802.11b/g/n single antenna.<br>-&nbsp;Supported maximum rate: 72.2 Mbps\@HT20&nbsp;MCS7<br>-&nbsp;20 MHz standard bandwidth and 5 MHz/10 MHz narrow bandwidth.<br>-&nbsp; STBC.<br>-&nbsp;Short-GI.|
| MAC features| -&nbsp;A-MPDU and A-MSDU.<br>-&nbsp;Blk-ACK.<br>-&nbsp;QoS to meet the quality requirements of different services.|
| CPU subsystem| - &nbsp;High-performance 32-bit microprocessor with a maximum working frequency of 160 MHz.<br>-&nbsp;Embedded SRAM of 352 KB; ROM of 288 KB<br>-&nbsp;Embedded 2 MB flash memory|
| Peripheral ports| -&nbsp;One SDIO interface, two SPI interfaces, two I2C interfaces, three UART interfaces, 15 GPIO interfaces, seven ADC inputs, six PWM interfaces, and one I2S interface (Note: These interfaces are all multiplexed.)<br>-&nbsp;Frequency of the external main crystal: 40 MHz or 24 MHz|
| Others| -&nbsp;Package: QFN-32, 5 mm x 5 mm<br>-&nbsp;Working temperature: -40°C to +85°C|
## OpenHarmony Key Features
OpenHarmony provides a wide array of available capabilities based on the Hi3861 platform. The following table describes the available key components.
**Table 2** Key components of OpenHarmony
| Component| Capability|
| -------- | -------- |
| WLAN| Provides the WLAN service capability. For example, connecting to or disconnecting from a station or hotspot, and querying the status of a station or hotspot.|
| IoT controller| Provides the capability of operating peripherals, including the I2C, I2S, ADC, UART, SPI, SDIO, GPIO, PWM and flash memory.|
| DSoftBus| Provides the capabilities of device discovery and data transmission in the distributed network.|
| hichainsdk| Provides the capability of securely transferring data between devices when they are interconnected.|
| huks| Provides capabilities of key management, encryption, and decryption.|
| System service management| Provides a unified OpenHarmony service development framework based on the service-oriented architecture.|
| Boot| Provides the entry identifier for starting a system service. When the system service management is started, the function identified by bootstrap is called to start a system service.|
| System attribute| Provides capabilities of obtaining and setting system attributes.|
| Base library| Provides the common basic library capability, including file operations and KV storage management.|
| DFX | Provides the DFX capability, such as logging and printing.|
| XTS | Provides a set of OpenHarmony certification test suites.|
# Mini and Small System Overview
## Introduction
The OpenHarmony mini and small systems apply to devices with a reference memory greater than or equal to 128 KiB. This document helps you quickly get started with development of the OpenHarmony mini and small systems, from environment setup to "Hello World" program running.
To accommodate different developer habits, OpenHarmony provides two modes for getting started with the standard system:
- IDE mode: DevEco Device Tool is used for one-stop development, covering dependency installation, building, burning, and running.
- Installation package mode: Dependency download and installation as well as building operations are performed using commands. Burning and running are performed in DevEco Device Tool.
OpenHarmony also provides the [Docker environment](../get-code/gettools-acquire.md), which can significantly simplify the environment configuration before compilation. You can build your source code in the Docker environment if you are more accustomed to using the installation package mode.
This document exemplifies how to use the IDE mode. For details about the installation package mode, see [Getting Started with Mini and Small Systems (Installation Package Mode)](../quick-start/quickstart-lite-package-directory.md).
## Development Environment
In the Windows+Ubuntu hybrid environment for OpenHarmony development:
- Windows: used for source code development and burning.
- Ubuntu: used for source code building.
This document describes how to develop OpenHarmony in the Windows+Ubuntu environment.
## Development Boards
In this document, two development board models are used as examples: Hi3861 and Hi3516D V300. For details about these development boards, see [Appendix](../quick-start/quickstart-ide-lite-board-introduction.md). You can purchase the development board as required.
## Development Process
Below you can see the quick start process for the development of the mini and small systems.
**Figure 1** Quick start process for the development of the mini and small systems
![en-us_image_0000001226634676](figures/en-us_image_0000001226634676.png)
# Obtaining Source Code
In the Ubuntu environment, perform the following steps to obtain the OpenHarmony source code:
## Preparations
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
3. Install the git client and git-lfs.
Update the software source:
```
sudo apt-get update
```
Run the following command to install the tools:
```
sudo apt-get install git git-lfs
```
4. Configure user information.
```
git config --global user.name "yourname"
git config --global user.email "your-email-address"
git config --global credential.helper store
```
5. Run the following commands to install the **repo** tool:
```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
```
## Obtaining Source Code
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master 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'
```
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'
```
- **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../../release-notes/Readme.md).
## Running prebuilts
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
```
# Writing a Hello World Program
The following exemplifies how to run the first program on the development board. The created program outputs the message "Hello World!" .
## Example Directory
The complete code directory is as follows:
```
applications/sample/hello
│── BUILD.gn
└── src
└── helloworld.c
```
## How to Develop
Perform the steps below in the source code directory:
1. Create a directory and the program source code.
Create the **applications/sample/hello/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **OHOS** to **World**. You can use either C or C++ to develop a program.
```
#include <stdio.h>
int main(int argc, char **argv)
{
printf("\n\n");
printf("\n\t\tHello OHOS!\n");
printf("\n\n\n");
return 0;
}
```
2. Create a build file.
Create the **applications/sample/hello/BUILD.gn** file. The file content is as follows:
```
import("//build/lite/config/component/lite_component.gni")
lite_component("hello-OHOS") {
features = [ ":helloworld" ]
}
executable("helloworld") {
output_name = "helloworld"
sources = [ "src/helloworld.c" ]
}
```
3. Add a component.
Modify the **build/lite/components/applications.json** file and add the configuration of **hello_world_app**. The following code snippet is a snippet of the **applications.json** file: The configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"components": [
{
"component": "camera_sample_communication",
"description": "Communication related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/communication"
],
"targets": [
"//applications/sample/camera/communication:sample"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##start##
{
"component": "hello_world_app",
"description": "hello world samples.",
"optional": "true",
"dirs": [
"applications/sample/hello"
],
"targets": [
"//applications/sample/hello:hello-OHOS"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##end##
{
"component": "camera_sample_app",
"description": "Camera related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/launcher",
"applications/sample/camera/cameraApp",
"applications/sample/camera/setting",
"applications/sample/camera/gallery",
"applications/sample/camera/media"
],
```
4. Modify the board configuration file.
Modify the **vendor/hisilicon/hispark_taurus/config.json** file and add an entry of the **hello_world_app** component. The following code snippet is the configuration of the **applications** subsystem, the configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"subsystem": "applications",
"components": [
{ "component": "camera_sample_app", "features":[] },
{ "component": "camera_sample_ai", "features":[] },
##start##
{ "component": "hello_world_app", "features":[] },
##end##
{ "component": "camera_screensaver_app", "features":[] }
]
},
```
# Building
1. In **Projects**, click **Settings**. The Hi3516D V300 configuration page is displayed.
![en-us_image_0000001265492885](figures/en-us_image_0000001265492885.png)
2. On the **toolchain** tab page, DevEco Device Tool automatically checks whether the dependent compilation toolchain is complete. If a message is displayed indicating that some tools are missing, click **SetUp** to automatically install the required tools.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the pip component fails to be installed, [change the Python](https://device.harmonyos.com/en/docs/documentation/guide/ide-set-python-source-0000001227639986) source and try again.
![en-us_image_0000001265652869](figures/en-us_image_0000001265652869.png)
After the toolchain is automatically installed, the figure below is displayed.
![en-us_image_0000001220852754](figures/en-us_image_0000001220852754.png)
3. On the **hi3516dv300** tab page, set **build_type**. The default value is **debug**. Click **Save** to save the settings.
![en-us_image_0000001221172710](figures/en-us_image_0000001221172710.png)
4. Choose **PROJECT TASKS** > **hi3516dv300** > **Build** to start building.
![en-us_image_0000001265772913](figures/en-us_image_0000001265772913.png)
5. Wait until **SUCCESS** is displayed in the **TERMINAL** window, indicating that the compilation is complete.
![en-us_image_0000001221012766](figures/en-us_image_0000001221012766.png)
After the building is complete, go to the out directory of the project to view the generated files, which are needed in [burning](https://device.harmonyos.com/en/docs/documentation/guide/ide-hi3516-upload-0000001052148681).
# Burning
Hi3516D V300 supports burning through the USB port, network port, and serial port. This document describes how to burn source code through the USB port. The operations are performed in Windows.
1. Connect the computer and the target development board through the serial port and USB port. For details, see [Introduction to the Hi3516D V300 Development Board](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-lite-introduction-hi3516.md).
2. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
3. Check the serial port number in **QUICK ACCESS** > **DevEco Home** > **Device** in DevEco Device Tool.
![en-us_image_0000001216516128](figures/en-us_image_0000001216516128.png)
> ![icon-note.gif](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/documentation/guide/hi3516_hi3518-drivers-0000001050743695).
4. Choose **QUICK ACCESS** > **DevEco Home** > **Projects**, and then click **Settings**.
![en-us_image_0000001198566364](figures/en-us_image_0000001198566364.png)
5. On the **hi3516dv300** tab page, set the burning options.
- **upload_partitions**: Select the file to be burnt. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are burnt at the same time.
- **upload_port**: Select the serial port number obtained.
- **upload_protocol**: Select the burning protocol **hiburn-usb**.
![en-us_image_0000001223190441](figures/en-us_image_0000001223190441.png)
6. Check the preset information of the files to be burnt and modify them when necessary. The files to be burnt include **fastboot**, **kernel**, **rootfs**, and **userfs**.
1. On the **hi3516dv300_fastboot** tab, select the items to be modified in **New Option**, such as **partition_bin**, **partition_addr**, and **partition_length**.
![en-us_image_0000001198889702](figures/en-us_image_0000001198889702.png)
2. In **Partition Options**, modify the items selected in the preceding step.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Set the start address and length of the partition based on the size of the files to be burnt. Make sure the size of the partition is greater than that of the files to be burnt and the partition addresses of the files to be burnt do not overlap.
![en-us_image_0000001243290907](figures/en-us_image_0000001243290907.png)
3. Follow the same procedure to modify the information about the **kernel**, **rootfs**, and **userfs** files.
7. When you finish modifying, click **Save** on the top.
8. Go to **hi3516dv300** > **Upload** to start burning.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If this is the first time you burn source code to 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 Port Driver on the Hi3516D V300 or Hi3518E V300 Development Board](https://device.harmonyos.com/en/docs/documentation/guide/usb_driver-0000001058690393) and start burning again.
![en-us_image_0000001267231481](figures/en-us_image_0000001267231481.png)
9. When the following information is displayed in the Terminal window, press and hold the reset button, remove and insert the USB cable, and release the reset button to start burning.
![en-us_image_0000001114129426](figures/en-us_image_0000001114129426.png)
If the following message is displayed, it indicates that the burning is successful.
![en-us_image_0000001160649343](figures/en-us_image_0000001160649343.png)
10. When the burning is successful, perform the operations in Running an Image to start the system.
# Running
## Starting the 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.
> ![icon-note.gif](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.
![en-us_image_0000001226794644](figures/en-us_image_0000001226794644.png)
2. When the message shown below is displayed, restart the development board. If "SUCCESS" is displayed, it indicates that the configuration is successful.
![en-us_image_0000001227114584](figures/en-us_image_0000001227114584.png)
3. Click **Monitor** on the taskbar to start the serial port tool.
![en-us_image_0000001271234705](figures/en-us_image_0000001271234705.png)
4. When the command output is displayed, press **Enter** until **OHOS #** is displayed, indicating that the system is started successfully.
![en-us_image_0000001271594709](figures/en-us_image_0000001271594709.png)
## Running a Hello World Program
After the system is started, perform the following steps to run the Hello World program:
1. Go to the **bin** directory on the startup page.
```
cd bin
```
2. Run the following command to run the **helloworld** program:
```
./helloworld
```
If the message "Hello World!" is displayed, the program runs successfully.
![en-us_image_0000001271354693](figures/en-us_image_0000001271354693.png)
## Next
Congratulations! You have finished all steps! Proceed to [develop a sample camera with a screen](https://gitee.com/openharmony/docs/blob/master/en/device-dev/guide/device-camera.md) to better familiarize yourself with OpenHarmony development.
# Hi3516 Development Board
- **[Writing a Hello World Program](quickstart-ide-lite-steps-hi3516-application-framework.md)**
- **[Building](quickstart-ide-lite-steps-hi3516-building.md)**
- **[Burning](quickstart-ide-lite-steps-hi3516-burn.md)**
- **[Running](quickstart-ide-lite-steps-hi3516-running.md)**
# Running
## Viewing Execution Result
After the sample code is compiled, burnt, run, and debugged, restart the development board. If the following messages are displayed, the image is running correctly:
```
ready to OS start
FileSystem mount ok.
wifi init success!
[DEMO] Hello world.
```
## Next
Congratulations! You have finished all steps! Proceed to [develop a sample WLAN product](https://gitee.com/openharmony/docs/blob/master/en/device-dev/guide/device-wlan.md) to better familiarize yourself with OpenHarmony development.
# Writing a Hello World Program
The following exemplifies how to create a program by modifying the source code. The created program outputs the message "Hello world." Perform the steps below in the source code directory.
1. Determine the directory structure.
Before compiling a service, you must create a directory (or a directory structure) in **./applications/sample/wifi-iot/app** to store source code files.
For example, add the **my_first_app** service to the **app** directory, where **hello_world.c** is the service code and **BUILD.gn** is the compilation script. The directory structure is shown as follows:
```
.
└── applications
└── sample
└── wifi-iot
└── app
└── my_first_app
│── hello_world.c
└── BUILD.gn
```
2. Write the service code.
Create the **hello_world.c** file in **./applications/sample/wifi-iot/app/my_first_app**. Then, create the service entry function **HelloWorld** in **hello_world.c** and implement service logic. Call **SYS_RUN()** of OpenHarmony to start the service. (**SYS_RUN** is defined in the **ohos_init.h** file.)
```
#include <stdio.h>
#include "ohos_init.h"
#include "ohos_types.h"
void HelloWorld(void)
{
printf("[DEMO] Hello world.\n");
}
SYS_RUN(HelloWorld);
```
3. Compile the **BUILD.gn** file for building services into a static library.
Create the **BUILD.gn** file in **./applications/sample/wifi-iot/app/my_first_app** and configure the file as follows:
The **BUILD.gn** file consists of three parts, including target, source file, and header file path. You need to fill in all of these parts.
```
static_library("myapp") {
sources = [
"hello_world.c"
]
include_dirs = [
"//utils/native/lite/include"
]
}
```
- Specify the compilation result named **libmyapp.a** in **static_library**. You can fill in this part based on your need.
- Specify the .c file on which a file depends and its path in **sources**. The path that contains **//** represents an absolute path (the code root path). The path that does not contain **//** is a relative path.
- Specify the path of .h file on which **sources** depends in **include_dirs**.
4. Add a component.
Modify the **build/lite/components/applications.json** file and add the configuration of **hello_world_app**. The following code snippet is a snippet of the **applications.json** file: The configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"components": [
{
"component": "camera_sample_communication",
"description": "Communication related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/communication"
],
"targets": [
"//applications/sample/camera/communication:sample"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##start##
{
"component": "hello_world_app",
"description": "hello world samples.",
"optional": "true",
"dirs": [
"applications/sample/wifi-iot/app/my_first_app"
],
"targets": [
"//applications/sample/wifi-iot/app/my_first_app:myapp"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_m" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##end##
{
"component": "camera_sample_app",
"description": "Camera related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/launcher",
"applications/sample/camera/cameraApp",
"applications/sample/camera/setting",
"applications/sample/camera/gallery",
"applications/sample/camera/media"
],
```
5. Modify the board configuration file.
Modify the **vendor/hisilicon/hispark_pegasus/config.json** file and add an entry of the **hello_world_app** component. The following code snippet is the configuration of the **applications** subsystem, the configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"subsystem": "applications",
"components": [
##start##
{ "component": "hello_world_app", "features":[] },
##end##
{ "component": "wifi_iot_sample_app", "features":[] }
]
},
```
# Building
1. In **Projects**, click **Settings**. The Hi3861 configuration page is displayed.
![en-us_image_0000001265785209](figures/en-us_image_0000001265785209.png)
2. On the **toolchain** tab page, DevEco Device Tool automatically checks whether the dependent compilation toolchain is complete. If a message is displayed indicating that some tools are missing, click **SetUp** to automatically install the required tools.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the pip component fails to be installed, [change the Python](https://device.harmonyos.com/en/docs/documentation/guide/ide-set-python-source-0000001227639986) source and try again.
![en-us_image_0000001221025048](figures/en-us_image_0000001221025048.png)
After the toolchain is automatically installed, the figure below is displayed.
![en-us_image_0000001221344980](figures/en-us_image_0000001221344980.png)
3. On the **hi3861** tab page, set **build_type**. The default value is **debug**. Click **Save** to save the settings.
![en-us_image_0000001265945173](figures/en-us_image_0000001265945173.png)
4. Choose **PROJECT TASKS** > **hi3861** > **Build** to start building.
![en-us_image_0000001265505181](figures/en-us_image_0000001265505181.png)
5. Wait until **SUCCESS** is displayed in the **TERMINAL** window, indicating that the compilation is complete.
![en-us_image_0000001265665157](figures/en-us_image_0000001265665157.png)
After the building is complete, go to the out directory of the project to view the generated files, which are needed in [burning](https://device.harmonyos.com/en/docs/documentation/guide/ide-hi3861-upload-0000001051668683).
# Burning
Hi3861 V100 supports burning through the serial port. To burn source code through the serial port in Windows, perform the following steps:
1. Connect the computer and the target development board through the serial port and USB port. For details, see [Introduction to the Hi3861 V100 Development Board](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-lite-introduction-hi3861.md).
2. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
3. Check the serial port number in **QUICK ACCESS** > **DevEco Home** > **Device** in DevEco Device Tool.
![en-us_image_0000001216274840](figures/en-us_image_0000001216274840.png)
> ![icon-note.gif](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 Hi3861 V100](https://device.harmonyos.com/en/docs/documentation/guide/hi3861-drivers-0000001058153433).
4. Choose **QUICK ACCESS** > **DevEco Home** > **Projects**, and then click **Settings**.
![en-us_image_0000001198943768](figures/en-us_image_0000001198943768.png)
5. On the **hi3861** tab page, set the burning options.
- **upload_port**: Select the serial port number obtained.
- **upload_protocol**: Select the burning protocol **hiburn-serial**.
- **upload_partitions**: Select the files to be burnt. **hi3861_app** is selected by default.
![en-us_image_0000001243704061](figures/en-us_image_0000001243704061.png)
6. Check the preset information of the files to be burnt and modify them when necessary.
On the **hi3861_app** tab page, select **partition_bin** from **New Option**, and set the path of the file to be burnt.
![en-us_image_0000001260919759](figures/en-us_image_0000001260919759.png)
7. When you finish modifying, click **Save** on the top.
8. Click **Open** to open the project file. Then, choose **PROJECT TASKS** > **hi3861** > **Upload** to start burning.
![en-us_image_0000001216440138](figures/en-us_image_0000001216440138.png)
9. When the following information is displayed, press the RST button on the development board to restart it.
![en-us_image_0000001198466090](figures/en-us_image_0000001198466090.png)
10. Wait until the burning is complete. When the following message is displayed, the burning is successful.
![en-us_image_0000001216761476](figures/en-us_image_0000001216761476.png)
# Debugging and Verification
When the burning and networking are complete, you can use either of the following methods to debug and verify whether the source code has been burnt correctly:
1. Using printf to print logs
2. Using ASM files to locate panic issues
As the example used here is simple, we use the printf method. The following describes the two methods in detail.
## printf
Add the printf function to the code, which helps print data to the serial port. You can add log printing in key service paths or service exception locations, as shown in the following figure.
```
void HelloWorld(void)
{
printf("[DEMO] Hello world.\n");
}
```
## Using ASM Files to Locate Issues
When the system exits abnormally, the call stack information about the abnormal exit is displayed on the serial port. Analyze the displayed information to troubleshoot and pinpoint issues.
```
=======KERNEL PANIC=======
**Call Stack*
Call Stack 0 -- 4860d8 addr:f784c
Call Stack 1 -- 47b2b2 addr:f788c
Call Stack 2 -- 3e562c addr:f789c
Call Stack 3 -- 4101de addr:f78ac
Call Stack 4 -- 3e5f32 addr:f78cc
Call Stack 5 -- 3f78c0 addr:f78ec
Call Stack 6 -- 3f5e24 addr:f78fc
Call Stack end***
```
To analyze the call stack information, the **Hi3861_wifiiot_app.asm** file is required. This file records the symbol addresses of the functions in the code in the flash memory and the disassembly information. The ASM file is built and output together with the version software package and is stored in the **./out/wifiiot/** directory.
1. Save the CallStack information to a .txt file for editing. (Optional)
2. Open the asm file, search for the addresses in CallStack, and list the corresponding function names. Generally, you only need to find the functions matching the first several stacks to locate issues.
```
Call Stack 0 -- 4860d8 addr:f784c -- WadRecvCB
Call Stack 1 -- 47b2b2 addr:f788c -- wal_sdp_process_rx_data
Call Stack 2 -- 3e562c addr:f789c
Call Stack 3 -- 4101de addr:f78ac
Call Stack 4 -- 3e5f32 addr:f78cc
Call Stack 5 -- 3f78c0 addr:f78ec
Call Stack 6 -- 3f5e24 addr:f78fc
```
3. Based on the call stack information, we can conclude that an exception occurs in the **WadRecvCB** function.
![en-us_image_0000001226634668](figures/en-us_image_0000001226634668.png)
4. Check and modify the code.
# Networking
After completing compilation and burning, perform the following to connect the Hi3861 WLAN module to the Internet using AT commands.
1. Click the icon of **DevEco: Serial Monitor** at the bottom of DevEco Device Tool to keep the connection between the Windows workstation and the Hi3861 WLAN module.
**Figure 1** Opening the DevEco Device Tool serial port
![en-us_image_0000001226634700](figures/en-us_image_0000001226634700.png)
2. Reset the Hi3861 WLAN module. The message **ready to OS start** is displayed on the **TERMINAL** panel, indicating that the WLAN module is started successfully.
**Figure 2** Successful resetting of the Hi3861 WLAN module
![en-us_image_0000001271594733](figures/en-us_image_0000001271594733.png)
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).
```
AT+STARTSTA # Start the STA mode.
AT+SCAN # Scan for available APs.
AT+SCANRESULT # Display the scanning result.
AT+CONN="SSID",,2,"PASSWORD" # Connect to the specified AP. (SSID and PASSWORD represent the name and password of the hotspot to be connected, respectively.)
AT+STASTAT # View the connection result.
AT+DHCP=wlan0,1 # Request the IP address of wlan0 from the AP using DHCP.
```
4. Check whether the Hi3861 WLAN module is properly connected to the gateway, as shown in the following figure.
```
AT+IFCFG # View the IP address assigned to an interface of the module.
AT+PING=X.X.X.X # Check the connectivity between the module and the gateway. Replace X.X.X.X with the actual gateway address.
```
**Figure 3** Successful networking of the Hi3861 WLAN module
![en-us_image_0000001227114612](figures/en-us_image_0000001227114612.png)
# Hi3861 Development Board
- **[Writing a Hello World Program](quickstart-ide-lite-steps-hi3861-application-framework.md)**
- **[Building](quickstart-ide-lite-steps-hi3861-building.md)**
- **[Burning](quickstart-ide-lite-steps-hi3861-burn.md)**
- **[Networking](quickstart-ide-lite-steps-hi3861-netconfig.md)**
- **[Debugging and Verification](quickstart-ide-lite-steps-hi3861-debug.md)**
- **[Running](quickstart-ide-lite-steps-hi3816-running.md)**
# Running a Hello World Program
- **[Hi3861 Development Board](quickstart-ide-lite-steps-hi3861.md)**
- **[Hi3516 Development Board](quickstart-ide-lite-steps-hi3516.md)**
# Getting Started for Mini and Small Systems (IDE Mode)
- **[Mini and Small System Overview](quickstart-ide-lite-overview.md)**
- **[Environment Preparation](quickstart-ide-lite-env-setup.md)**
- **[Creating a Source Code Project](quickstart-ide-lite-create-project.md)**
- **[Running a Hello World Program](quickstart-ide-lite-steps.md)**
- **[Appendix](quickstart-ide-lite-appendix.md)**
# Appendix
- **[Introduction to Development Boards](quickstart-ide-standard-board-introduction.md)**
# Introduction to the Hi3516 Development Board
## Overview
Hi3516D V300 is a next-generation system on chip (SoC) designed for industry-dedicated smart HD IP cameras. 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** Hi3516 front view
![en-us_image_0000001227082182](figures/en-us_image_0000001227082182.png)
## Development Board Specifications
**Table 1** Hi3516 specifications
| Item| Description|
| -------- | -------- |
| Processor and internal memory| -&nbsp;Hi3516D V300 chip<br>-&nbsp;DDR3&nbsp;1GB<br>-&nbsp;eMMC 4.5, 8 GB capacity|
| External components| -&nbsp;Ethernet port<br>-&nbsp;Audio and video<br>&nbsp;&nbsp;-&nbsp;1 voice input<br>&nbsp;&nbsp;-&nbsp;1 mono channel (AC_L) output, connected to a 3 W power amplifier (LM4871)<br>&nbsp;&nbsp;-&nbsp;MicroHDMI (1-channel HDMI 1.4)<br>-&nbsp;Camera<br>&nbsp;&nbsp;-&nbsp;Sensor IMX335<br>&nbsp;&nbsp;-&nbsp;M12 lens, 4 mm focal length, and 1.8 aperture<br>-&nbsp;Display<br>&nbsp;&nbsp;-&nbsp;LCD connector (2.35-inch)<br>&nbsp;&nbsp;-&nbsp;LCD connector (5.5-inch)<br>-&nbsp;External components and ports<br>&nbsp;&nbsp;-&nbsp;Memory card port<br>&nbsp;&nbsp;-&nbsp;JTAG/I2S port<br>&nbsp;&nbsp;-&nbsp;ADC port<br>&nbsp;&nbsp;-&nbsp;Steering gear port<br>&nbsp;&nbsp;-&nbsp;Grove connector<br>&nbsp;&nbsp;-&nbsp;USB 2.0 (Type-C)<br>&nbsp;&nbsp;-&nbsp;Three function keys, two user-defined keys, and one upgrade key<br>&nbsp;&nbsp;-&nbsp;LED indicator, green or red|
# Introduction to the RK3568 Development Board
## Overview
Bolstered by the Rockchip RK3568 chip, the RK3568 development board integrates a dual-core GPU and high-efficiency NPU. Its quad-core 64-bit Cortex-A55 processor uses the advanced 22 nm manufacturing process and is clocked at up to 2.0 GHz. The development board is packed with Bluetooth, Wi-Fi, audio, video, and camera features, with a wide range of expansion ports as well as video input and output ports. It comes with dual GE auto-sensing RJ45 ports, so it can be used in multi-connectivity products, such as NVRs and industrial gateways.
**Figure 1** Front view of the RK3568 development board
![en-us_image_0000001271442261](figures/en-us_image_0000001271442261.png)
**Figure 2** RK3568 rear view
![en-us_image_0000001271322293](figures/en-us_image_0000001271322293.png)
## Development Board Specifications
**Table 1** RK3568 specifications
| Item| Description|
| -------- | -------- |
| Display| -&nbsp;1 x HDMI 2.0 (Type-A) port, supporting 4K/60 fps output<br>-&nbsp;2 x MIPI, supporting 1920 x 1080\@60 fps output<br>-&nbsp; 1 x eDP, supporting 2K@60 fps output|
| Audio port| -&nbsp;1×8ch&nbsp;I2S/TDM/PDM<br>-&nbsp;1 x HDMI<br>-&nbsp;1 x speaker output<br>-&nbsp;1 x headset output<br>-&nbsp;1 x microphone for onboard audio input|
| Ethernet port| 2 x GMAC (10/100/1000M)|
| Wireless connectivity| SDIO port, supporting Wi-Fi 6 5G/2.5 GHz and Bluetooth 4.2|
| Camera port| MIPI-CSI2, 1 x 4-lane/2x2-lane\@2.5 Gbps/lane|
| USB | -&nbsp;2 x USB 2.0 Host, Type-A<br>-&nbsp;1 x USB 3.0 Host, Type-A<br>-&nbsp;1×USB3.0&nbsp;OTG |
| PCIe | 1 x 2-lane PCIe 3.0 Connector (RC mode)|
| SATA | 1×SATA3.0&nbsp;Connector |
| SDMMC | 1×Micro&nbsp;SD&nbsp;Card3.0 |
| Keys| -&nbsp;1×Vol+/Recovery<br>-&nbsp;1×Reset<br>-&nbsp;1×Power<br>-&nbsp;1×Vol-<br>-&nbsp;1×Mute |
| Debugging port| 1 x Debugging serial port|
| RTC | 1 x RTC |
| IR | 1 x IR |
| Tri-color indicator| 3 x LED |
| G-sensor | 1 x G-sensor |
| Fan | 1 x fan |
| Expansion port| The 20-pin expansion ports include:<br>-&nbsp;2 x ADC<br>-&nbsp; 2 x I2C<br>-&nbsp;7 x GPIO (or 3 x GPIO + 4 x UART)<br>-&nbsp;3 x VCC power (12 V, 3.3 V, and 5 V)|
| Mother board dimensions| 180mm×130mm |
| PCB| 4-laminate|
# Introduction to Development Boards
- **[Introduction to the Hi3516 Development Board](quickstart-ide-standard-board-introduction-hi3516.md)**
- **[Introduction to the RK3568 Development Board](quickstart-ide-standard-board-introduction-rk3568.md)**
# Creating a Source Code Project
After [setting up the Windows+Ubuntu hybrid development environment](../quick-start/quickstart-ide-standard-env-setup-win-ubuntu.md) and [obtaining source code](../quick-start/quickstart-ide-standard-sourcecode-acquire.md), perform the following steps to create a source code project in Windows:
1. Open DevEco Device Tool, go to the home page, and click **Import Project** to open your project or source code.
![en-us_image_0000001171426014](figures/en-us_image_0000001171426014.png)
2. Select the source code directory to be imported and click **Import**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Make sure the selected directory does not contain Chinese characters or spaces. Otherwise, the building may fail.
![en-us_image_0000001271562277](figures/en-us_image_0000001271562277.png)
3. If you select to open the OpenHarmony source code, a message will be displayed indicating that the project is not a DevEco Device Tool project. Click **Import** to continue.
![en-us_image_0000001135394334](figures/en-us_image_0000001135394334.png)
4. On the **Select Project type** page, select **Import from OpenHarmony Source**.
![en-us_image_0000001215743910](figures/en-us_image_0000001215743910.png)
5. On the **Import Project** page, select a product, and the MCU, board, company, and kernel fields will be automatically populated. Then, select the OpenHarmony source code version for **ohosVersion**. The following figure uses **Hi3516DV300** as an example.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - Set **Product** to **Hi3516DV300** for the Hi3516D V300 development board.
>
> - Set **Product** to **rk3568** for the RK3568 development board.
![en-us_image_0000001271448821](figures/en-us_image_0000001271448821.png)
6. Click **Open** to open the project or source code.
# Setting Up the Windows+Ubuntu Hybrid Development Environment
In embedded development, Windows-based tools, such as Visual Studio Code, are widely used in code editing. Yet, as the source code of most development boards, such as Hi3861 and Hi3516, cannot be built in Windows, these development boards require the Ubuntu build environment.
In the Windows+Ubuntu hybrid build environment, you can enjoy the benefits of both DevEco Device Tool for Windows and DevEco Device Tool for Ubuntu (where Visual Studio Code is optional).
## System Requirements
- Windows: Windows 10 (64-bit)
- Ubuntu: Ubuntu 20.04 or later; recommended memory: 16 GB or higher.
- User name: cannot contain Chinese characters
- DevEco Device Tool: 3.0 Release
## Setting Up the Ubuntu Build Environment
The setup procedure varies, depending on whether you need a GUI. If you need a GUI, you need to install Visual Studio Code. In this case, follow the instructions in [Setting Up the Ubuntu Development Environment](https://device.harmonyos.com/en/docs/documentation/guide/ide-install-ubuntu-0000001072959308). If you do not need a GUI, perform the steps below:
1. Make sure the Ubuntu shell environment is **bash**.
1. Run the following command and check whether the command output is **bash**. If the command output is not **bash**, go to step 2.
```
ls -l /bin/sh
```
![en-us_image_0000001226764302](figures/en-us_image_0000001226764302.png)
2. Start the command-line tool, run the following command, enter your password, and select **No** to set **Ubuntu shell** to **bash**.
```
sudo dpkg-reconfigure dash
```
![en-us_image_0000001243641075](figures/en-us_image_0000001243641075.png)
2. Download the [DevEco Device Tool 3.0 Release Linux version](https://device.harmonyos.com/cn/ide#download).
3. Decompress the DevEco Device Tool software package and assign permission on the folder obtained from the decompression.
1. Go to the directory where the DevEco Device Tool software package is stored and run the following command to decompress the software package. In the command, change **devicetool-linux-tool-3.0.0.400.zip** to the actual software package name.
```
unzip devicetool-linux-tool-3.0.0.400.zip
```
2. Open the folder of the decompressed software package and run the following command to grant the execute permission on the installation file. In the command, change **devicetool-linux-tool-3.0.0.400.sh** to the actual installation file name.
```
chmod u+x devicetool-linux-tool-3.0.0.400.sh
```
4. Run the following command to install DevEco Device Tool, where **devicetool-linux-tool-3.0.0.400.sh** indicates the installation file name.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> During the installation, the setup wizard automatically checks whether Python 3.8 or 3.9 is installed. If Python 3.8 or 3.9 is not installed, the setup wizard displays the "Do you want to continue?" message; enter **Y** to allow the setup wizard to automatically install Python.
```
sudo ./devicetool-linux-tool-3.0.0.400.sh
```
Wait until the "Deveco Device Tool successfully installed." message is displayed.
![en-us_image_0000001198722374](figures/en-us_image_0000001198722374.png)
## Setting Up Windows Development Environment
To remotely access the Ubuntu environment through Windows and enjoy the benefits of DevEco Device Tool for Windows, you need to install DevEco Device Tool on Windows.
1. Download the [DevEco Device Tool 3.0 Release](https://device.harmonyos.com/cn/ide#download) Windows edition.
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**. You are advised to install DevEco Device Tool in a non-system drive.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If you have installed DevEco Device Tool 3.0 Beta2 or earlier, the earlier version will be uninstalled before you install a new version. If the following error message is displayed during the uninstallation, click **Ignore** to continue the installation. This error does not affect the installation of the new version.
>
> ![en-us_image_0000001239275843](figures/en-us_image_0000001239275843.png)
![en-us_image_0000001270076961](figures/en-us_image_0000001270076961.png)
4. When prompted, select the tools to be automatically installed.
1. On the **VSCode installation confirm** page, select **Install VScode 1.62.2 automatically** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Visual Studio Code 1.62 or later has been installed, this step will be skipped.
![en-us_image_0000001237801283](figures/en-us_image_0000001237801283.png)
2. On the displayed **Python select page**, select **Download from Huawei mirror** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Python 3.8 or 3.9 has been installed, select **Use one of compatible on your PC**.
![en-us_image_0000001193983334](figures/en-us_image_0000001193983334.png)
5. In the dialog box shown below, click **Next** to download and install the tools..
![en-us_image_0000001239634067](figures/en-us_image_0000001239634067.png)
6. Wait for the DevEco Device Tool setup wizard to automatically install DevEco Device Tool. After the installation is complete, click **Finish** to close the setup wizard.
![en-us_image_0000001239650137](figures/en-us_image_0000001239650137.png)
7. From Visual Studio Code, access the DevEco Device Tool page. Now you can conduct your development in DevEco Device Tool.
![en-us_image_0000001225760456](figures/en-us_image_0000001225760456.png)
## Configuring Windows to Remotely Access the Ubuntu Build Environment
### Installing the SSH Service and Obtaining the IP Address for Remote Access
1. In Ubuntu, open the Terminal tool and run the following command to install the SSH service:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the command fails to be executed and the system displays a message indicating that the openssh-server and openssh-client depend on different versions, install the openssh-client of the required version (for example, **sudo apt-get install openssh-client=1:8.2p1-4**) as prompted on the command-line interface (CLI) and run the command again to install the openssh-server.
```
sudo apt-get install openssh-server
```
2. Run the following command to start the SSH service:
```
sudo systemctl start ssh
```
3. Run the following command to obtain the IP address of the current user for remote access to the Ubuntu environment from Windows:
```
ifconfig
```
![en-us_image_0000001215737140](figures/en-us_image_0000001215737140.png)
### Installing Remote SSH
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001239080359](figures/en-us-cn_image_0000001239080359.png), and search for **remote-ssh** in the Extension Marketplace.
![en-us_image_0000001193920448](figures/en-us_image_0000001193920448.png)
2. Click **Install** to install Remote-SSH. After the installation is successful, **Remote-SSH** is displayed on the **INSTALLED** list.
![en-us_image_0000001238880335](figures/en-us_image_0000001238880335.png)
### Remotely Connecting to the Ubuntu Environment
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001238760373](figures/en-us_image_0000001238760373.png), and click + on the **REMOTE EXOPLORER** page.
![en-us_image_0000001215878922](figures/en-us_image_0000001215878922.png)
2. In the **Enter SSH Connection Command** text box, enter **ssh *username@ip_address***, where *ip_address* indicates the IP address of the remote computer to be connected and *username* indicates the account name used for logging in to the remote computer.
![en-us_image_0000001215879750](figures/en-us_image_0000001215879750.png)
3. In the displayed dialog box, select the default first option as the SSH configuration file.
![en-us_image_0000001260519729](figures/en-us_image_0000001260519729.png)
4. Under **SSH TARGETS**, find the remote computer and click ![en-us_image_0000001194080414](figures/en-us_image_0000001194080414.png) to start it.
![en-us_image_0000001215720398](figures/en-us_image_0000001215720398.png)
5. In the displayed dialog box, select **Linux**, select **Continue**, and enter the password for logging in to the remote computer.
![en-us_image_0000001215897530](figures/en-us_image_0000001215897530.png)
After the connection is successful, the plug-in is automatically installed in the .vscode-server folder on the remote computer. After the installation is complete, reload Visual Studio Code in Windows as prompted. Then you can develop, compile, and burn source code in DevEco Device Tool on Windows.
### Registering the Public Key for Accessing the Ubuntu Environment
After the preceding operations are complete, you can remotely connect to the Ubuntu environment through Windows for development. However, you need to frequently enter the remote connection password. To eliminate this need, you can use the SSH public key.
1. Open the Git bash CLI and run the following command to generate an SSH public key. During command execution, perform operations as prompted. Set **username** and **ip** to the user name and IP address you use for connecting to the Ubuntu system.
```
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip
```
![en-us_image_0000001271532317](figures/en-us_image_0000001271532317.png)
2. In Visual Studio Code, click the remote connection setting button and open the **config** file.
![en-us_image_0000001226034634](figures/en-us_image_0000001226034634.png)
3. In the **config** file, add the SSK key file information, as shown below. Then save the file.
![en-us_image_0000001270356233](figures/en-us_image_0000001270356233.png)
# Environment Preparation
- **[Setting Up the Windows+Ubuntu Hybrid Build Environment](quickstart-ide-standard-env-setup-win-ubuntu.md)**
- **[Obtaining Source Code](quickstart-ide-standard-sourcecode-acquire.md)**
# Standard System Overview
## Introduction
The OpenHarmony standard system applies to devices with a reference memory greater than or equal to 128 MiB. This document helps you quickly get started for development of the OpenHarmony standard system, from environment setup to building, burning, and startup.
To accommodate different developer habits, OpenHarmony provides two modes for getting started with the standard system:
- IDE mode: DevEco Device Tool is used for one-stop development, covering dependency installation, building, burning, and running.
- Installation package mode: Dependency download and installation as well as building operations are performed using commands. Burning and running are performed in DevEco Device Tool.
OpenHarmony also provides the [Docker environment](../get-code/gettools-acquire.md), which can significantly simplify the environment configuration before compilation. You can build your source code in the Docker environment if you are more accustomed to using the installation package mode.
This document exemplifies how to use the IDE mode. For details about the installation package mode, see [Getting Started with Standard System (Installation Package Mode)](../quick-start/quickstart-standard-package-directory.md).
## Development Environment
In the Windows+Ubuntu hybrid environment for OpenHarmony development:
- Windows: used for source code development and burning.
- Ubuntu: used for source code building.
This document describes how to develop OpenHarmony in the Windows+Ubuntu environment.
## Development Boards
In this document, two development board models are used as examples: Hi3516D V300 and RK3568. For details about these development boards, see [Appendix](../quick-start/quickstart-standard-board-introduction.md). You can purchase the development board as required.
## Development Process
Below you can see the quick start process for the development of the standard system.
**Figure 1** Quick start process for the development of the standard system
![en-us_image_0000001271562257](figures/en-us_image_0000001271562257.png)
# Building
1. In **Projects**, click **Settings**. The Hi3516D V300 configuration page is displayed.
![en-us_image_0000001265492885](figures/en-us_image_0000001265492885.png)
2. On the **toolchain** tab page, DevEco Device Tool automatically checks whether the dependent compilation toolchain is complete. If a message is displayed indicating that some tools are missing, click **SetUp** to automatically install the required tools.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the pip component fails to be installed, [change the Python](https://device.harmonyos.com/en/docs/documentation/guide/ide-set-python-source-0000001227639986) source and try again.
![en-us_image_0000001227277128](figures/en-us_image_0000001227277128.png)
After the toolchain is automatically installed, the figure below is displayed.
![en-us_image_0000001227757036](figures/en-us_image_0000001227757036.png)
3. On the **hi3516dv300** tab page, set **build_type**. The default value is **debug**. Click **Save** to save the settings.
![en-us_image_0000001221172710](figures/en-us_image_0000001221172710.png)
4. Choose **PROJECT TASKS** > **hi3516dv300** > **Build** to start building.
![en-us_image_0000001265772913](figures/en-us_image_0000001265772913.png)
5. Wait until **SUCCESS** is displayed in the **TERMINAL** window, indicating that the compilation is complete.
![en-us_image_0000001221012766](figures/en-us_image_0000001221012766.png)
After the building is complete, go to the out directory of the project to view the generated files, which are needed in [burning](https://device.harmonyos.com/en/docs/documentation/guide/ide-hi3516-upload-0000001052148681).
# Burning
To burn source code to Hi3516D V300 through the USB port in Windows, perform the following steps:
1. Connect the computer and the target development board through the serial port and USB port. For details, see [Introduction to the Hi3516D V300 Development Board](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-lite-introduction-hi3516.md).
2. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
3. Check the serial port number in **QUICK ACCESS** > **DevEco Home** > **Device** in DevEco Device Tool.
![en-us_image_0000001216516128](figures/en-us_image_0000001216516128.png)
> ![icon-note.gif](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/documentation/guide/hi3516_hi3518-drivers-0000001050743695).
4. Choose **QUICK ACCESS** > **DevEco Home** > **Projects**, and then click **Settings**.
![en-us_image_0000001198566364](figures/en-us_image_0000001198566364.png)
5. On the **hi3516dv300** tab page, set the burning options.
- **upload_partitions**: Select the file to be burnt. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are burnt at the same time.
- **upload_port**: Select the serial port number obtained.
- **upload_protocol**: Select the burning protocol **hiburn-usb**.
![en-us_image_0000001223190441](figures/en-us_image_0000001223190441.png)
6. Check the preset information of the files to be burnt and modify them when necessary. The files to be burnt include **fastboot**, **kernel**, **rootfs**, and **userfs**.
1. On the **hi3516dv300_fastboot** tab, select the items to be modified in **New Option**, such as **partition_bin**, **partition_addr**, and **partition_length**.
![en-us_image_0000001198889702](figures/en-us_image_0000001198889702.png)
2. In **Partition Options**, modify the items selected in the preceding step.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Set the start address and length of the partition based on the size of the files to be burnt. Make sure the size of the partition is greater than that of the files to be burnt and the partition addresses of the files to be burnt do not overlap.
![en-us_image_0000001243290907](figures/en-us_image_0000001243290907.png)
3. Follow the same procedure to modify the information about the **kernel**, **rootfs**, and **userfs** files.
7. When you finish modifying, click **Save** on the top.
8. Go to **hi3516dv300** > **Upload** to start burning.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If this is the first time you burn source code to 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 Port Driver on the Hi3516D V300 or Hi3518E V300 Development Board](https://device.harmonyos.com/en/docs/documentation/guide/usb_driver-0000001058690393) and start burning again.
![en-us_image_0000001267231481](figures/en-us_image_0000001267231481.png)
9. When the following information is displayed in the Terminal window, press and hold the reset button, remove and insert the USB cable, and release the reset button to start burning.
![en-us_image_0000001114129426](figures/en-us_image_0000001114129426.png)
If the following message is displayed, it indicates that the burning is successful.
![en-us_image_0000001160649343](figures/en-us_image_0000001160649343.png)
10. When the burning is successful, perform the operations in Running an Image to start the system.
# Writing a Hello World Program
The following exemplifies how to run the first program on the development board. The created program outputs the message "Hello World!" .
## Example Directory
The complete code directory is as follows:
```
applications/sample/hello
│── BUILD.gn
│── include
│ └── helloworld.h
│── src
│ └── helloworld.c
├── bundle.json
build
└── subsystem_config.json
productdefine/common
└── products
└── Hi3516DV300.json
```
## How to Develop
Perform the steps below in the source code directory:
1. Create a directory and write the service code.
Create the **applications/sample/hello/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **World** to **OHOS**. Declare the string printing function **HelloPrint** in the **helloworld.h** file. You can use either C or C++ to develop a program.
```
#include <stdio.h>
#include "helloworld.h"
int main(int argc, char **argv)
{
HelloPrint();
return 0;
}
void HelloPrint()
{
printf("\n\n");
printf("\n\t\tHello World!\n");
printf("\n\n");
}
```
Add the header file **applications/sample/hello/include/helloworld.h**. The sample code is as follows:
```
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
void HelloPrint();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // HELLOWORLD_H
```
2. Create a build file.
1. Create the **applications/sample/hello/BUILD.gn** file. The file content is as follows:
```
import("//build/ohos.gni") # Import the build template.
ohos_executable("helloworld") {# Executable module.
sources = [ # Source code of the module.
"src/helloworld.c"
]
include_dirs = [ # Directory of header file on which the module depends.
"include"
]
cflags = []
cflags_c = []
cflags_cc = []
ldflags = []
configs = []
deps =[] # Internal dependencies of a component.
part_name = "hello" # Component name. This parameter is mandatory.
install_enable = true # Whether to install the software by default. This parameter is optional. By default, the software is not installed.
}
```
2. Create the **applications/sample/hello/bundle.json** file and add the description of the **sample** component. The content is as follows:
```
{
"name": "@ohos/hello",
"description": "Hello world example.",
"version": "3.1",
"license": "Apache License 2.0",
"publishAs": "code-segment",
"segment": {
"destPath": "applications/sample/hello"
},
"dirs": {},
"scripts": {},
"component": {
"name": "hello",
"subsystem": "sample",
"syscap": [],
"features": [],
"adapted_system_type": [ "mini", "small", "standard" ],
"rom": "10KB",
"ram": "10KB",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [
"//applications/sample/hello:helloworld"
],
"inner_kits": [],
"test": []
}
}
}
```
The **bundle.json** file consists of two parts. The first part describes the information about the subsystem to which the component belongs, and the second part defines the component building configuration. When adding a part, you need to specify the **sub_component** contained in the part. If there are interfaces provided for other components, describe them in **inner_kits**. If there are test cases, describe them in **test**.
3. Modify the subsystem configuration file.
Add the configuration of the new subsystem to the **build/subsystem_config.json** file.
```
"sample": {
"path": "applications/sample/hello",
"name": "sample"
},
```
4. Modify the product configuration file.
In the productdefine\common\products\Hi3516DV300.json file, add the hello part after the existing part.
```
"usb:usb_manager_native":{},
"applications:prebuilt_hap":{},
"sample:hello":{},
"wpa_supplicant-2.9:wpa_supplicant-2.9":{},
```
# Running
## Starting the System
After the burning is complete, perform the following steps to start the system:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation procedure is required only if this is the first time you burn an image for the standard system.
1. In DevEco Device Tool, click **Monitor** to open the serial port tool.
![en-us_image_0000001227082162](figures/en-us_image_0000001227082162.png)
2. Restart the development board. Before the autoboot countdown ends, press any key to enter the system.
![en-us_image_0000001271202289](figures/en-us_image_0000001271202289.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 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 0x82000000 0x800 0x4800; bootm 0x82000000'
```
![en-us_image_0000001271562269](figures/en-us_image_0000001271562269.png)
4. Save the parameter settings.
```
save
```
![en-us_image_0000001226762210](figures/en-us_image_0000001226762210.png)
5. Restart the development board to start the system.
```
reset
```
![en-us_image_0000001226602238](figures/en-us_image_0000001226602238.png)
## Running a Hello World Program
After the system is started, start the serial port tool, run the **helloworld** command in any directory, and press **Enter**. If the message "Hello World!" is displayed, the program runs successfully.
![en-us_image_0000001271322277](figures/en-us_image_0000001271322277.png)
## Next
Congratulations! You have finished all steps! Proceed to [develop a sample](../guide/device-clock-guide.md) to better familiarize yourself with OpenHarmony development.
# Hi3516 Development Board
- **[Writing a Hello World Program](quickstart-ide-standard-running-hi3516-create.md)**
- **[Building](quickstart-ide-standard-running-hi3516-build.md)**
- **[Burning](quickstart-ide-standard-running-hi3516-burning.md)**
- **[Running](quickstart-ide-standard-running-hi3516-running.md)**
# Building
1. In **Projects**, click **Settings**. The HH-SCDY200 configuration page is displayed.
![en-us_image_0000001221036768](figures/en-us_image_0000001221036768.png)
2. On the **toolchain** tab page, DevEco Device Tool automatically checks whether the dependent compilation toolchain is complete. If a message is displayed indicating that some tools are missing, click **SetUp** to automatically install the required tools.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the pip component fails to be installed, [change the Python](https://device.harmonyos.com/en/docs/documentation/guide/ide-set-python-source-0000001227639986) source and try again.
![en-us_image_0000001221356692](figures/en-us_image_0000001221356692.png)
After the toolchain is automatically installed, the figure below is displayed.
![en-us_image_0000001265676877](figures/en-us_image_0000001265676877.png)
3. On the **hh_scdy200** tab page, set **build_type**. The default value is **debug**. Click **Save** to save the settings.
![en-us_image_0000001265956897](figures/en-us_image_0000001265956897.png)
4. Choose **PROJECT TASKS** > **hi3861** > **Build** to start building.
![en-us_image_0000001265516901](figures/en-us_image_0000001265516901.png)
5. Wait until **SUCCESS** is displayed in the **TERMINAL** window, indicating that the compilation is complete.
![en-us_image_0000001222361042](figures/en-us_image_0000001222361042.png)
After the building is complete, go to the out directory of the project to view the generated files, which are needed in [burning](https://device.harmonyos.com/en/docs/documentation/guide/ide-rk3568-upload-0000001239220669).
# Burning
1. [Download](https://gitee.com/hihope_iot/docs/blob/master/HiHope_DAYU200/%E7%83%A7%E5%86%99%E5%B7%A5%E5%85%B7%E5%8F%8A%E6%8C%87%E5%8D%97/windows/DriverAssitant_v5.1.1.zip) **DriverInstall.exe**. Double-click **DriverInstall.exe** to open the installer. Then click the install button to install the USB driver as prompted.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the burning tool of an earlier version has been installed, uninstall it first.
2. Connect the computer to the target development board through the USB port.
3. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
4. In DevEco Device Tool, choose QUICK ACCESS > DevEco Home > Projects, and then click Settings.
![en-us_image_0000001239661509](figures/en-us_image_0000001239661509.png)
5. On the **hh_scdy200** tab page, set the burning options.
- **upload_partitions**: Select the files to be burnt.
- **upload_protocol**: Select the burning protocol **upgrade**.
![en-us_image_0000001194504874](figures/en-us_image_0000001194504874.png)
6. Check the preset information of the files to be burnt and modify them when necessary. The files to be burnt include **loader**, **parameter**, **uboot**, **boot_linux**, **system**, **vendor**, and **userdata**.
1. On the **hh_scdy200_loader** tab, select the items to be modified in **New Option**, such as **partition_bin**, **partition_addr**, and **partition_length**.
![en-us_image_0000001224173270](figures/en-us_image_0000001224173270.png)
2. In **Partition Options**, modify the items selected in the preceding step.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Set the start address and length of the partition based on the size of the files to be burnt. Make sure the size of the partition is greater than that of the files to be burnt and the partition addresses of the files to be burnt do not overlap.
![en-us_image_0000001268653461](figures/en-us_image_0000001268653461.png)
3. Follow the same procedure to modify the information about the **parameter**, **uboot**, **boot_linux**, **system**, **vendor**, and **userdata** files.
7. When you finish modifying, click **Save** on the top.
8. Click **Open** to open the project file. Click ![en-us_image_0000001239221905](figures/en-us_image_0000001239221905.png) to open DevEco Device Tool. Then, choose **PROJECT TASKS** > **hh_scdy200** > **Upload** to start burning.
![en-us_image_0000001194821710](figures/en-us_image_0000001194821710.png)
9. Wait until the burning is complete. If the following message is displayed, the burning is successful.
![en-us_image_0000001194984912](figures/en-us_image_0000001194984912.png)
# Writing a Hello World Program
The following exemplifies how to run the first program on the development board. The created program outputs the message "Hello World!" .
## Example Directory
The complete code directory is as follows:
```
applications/sample/hello
│── BUILD.gn
│── include
│ └── helloworld.h
│── src
│ └── helloworld.c
├── bundle.json
build
└── subsystem_config.json
productdefine/common
└── products
└── rk3568.json
```
## How to Develop
Perform the steps below in the source code directory:
1. Create a directory and write the service code.
Create the **applications/sample/hello/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **World** to **OHOS**. Declare the string printing function **HelloPrint** in the **helloworld.h** file. You can use either C or C++ to develop a program.
```
#include <stdio.h>
#include "helloworld.h"
int main(int argc, char **argv)
{
HelloPrint();
return 0;
}
void HelloPrint()
{
printf("\n\n");
printf("\n\t\tHello World!\n");
printf("\n\n");
}
```
Add the header file **applications/sample/hello/include/helloworld.h**. The sample code is as follows:
```
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
void HelloPrint();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // HELLOWORLD_H
```
2. Create a build file.
1. Create the **applications/sample/hello/BUILD.gn** file. The file content is as follows:
```
import("//build/ohos.gni") # Import the build template.
ohos_executable("helloworld") {# Executable module.
sources = [ # Source code of the module.
"src/helloworld.c"
]
include_dirs = [ # Directory of header file on which the module depends.
"include"
]
cflags = []
cflags_c = []
cflags_cc = []
ldflags = []
configs = []
deps =[] # Internal dependencies of a component.
part_name = "hello" # Component name. This parameter is mandatory.
install_enable = true # Whether to install the software by default. This parameter is optional. By default, the software is not installed.
}
```
2. Create the **applications/sample/hello/bundle.json** file and add the description of the **sample** component. The content is as follows:
```
{
"name": "@ohos/hello",
"description": "Hello world example.",
"version": "3.1",
"license": "Apache License 2.0",
"publishAs": "code-segment",
"segment": {
"destPath": "applications/sample/hello"
},
"dirs": {},
"scripts": {},
"component": {
"name": "hello",
"subsystem": "sample",
"syscap": [],
"features": [],
"adapted_system_type": [ "mini", "small", "standard" ],
"rom": "10KB",
"ram": "10KB",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [
"//applications/sample/hello:helloworld"
],
"inner_kits": [],
"test": []
}
}
}
```
The **bundle.json** file consists of two parts. The first part describes the information about the subsystem to which the component belongs, and the second part defines the component building configuration. When adding a part, you need to specify the **sub_component** contained in the part. If there are interfaces provided for other components, describe them in **inner_kits**. If there are test cases, describe them in **test**.
3. Modify the subsystem configuration file.
Add the configuration of the new subsystem to the **build/subsystem_config.json** file.
```
"sample": {
"path": "applications/sample/hello",
"name": "sample"
},
```
4. Modify the product configuration file.
In the productdefine\common\products\rk3568.json file, add the hello part after the existing part.
```
"usb:usb_manager_native":{},
"applications:prebuilt_hap":{},
"sample:hello":{},
"wpa_supplicant-2.9:wpa_supplicant-2.9":{},
```
# Running
## Starting the System
After the image is burnt and the development board is restarted, the system automatically starts. If the following page is displayed on the screen of the development board, the system is running properly.
**Figure 1** System startup effect
![en-us_image_0000001226762222](figures/en-us_image_0000001226762222.jpg)
## Running a Hello World Program
1. When the system is running, start the serial port tool (for example, PuTTY), set the baud rate to **1500000**, and connect to the device.
![en-us_image_0000001226602250](figures/en-us_image_0000001226602250.png)
2. Enable the serial port, enter the **helloworld** command in any directory (for example, the root directory of the device) and press **Enter**. If the message "Hello World!" is displayed, the program runs successfully.
![en-us_image_0000001226922154](figures/en-us_image_0000001226922154.png)
# RK3568 Development Board
- **[Writing a Hello World Program](quickstart-ide-standard-running-rk3568-create.md)**
- **[Building](quickstart-ide-standard-running-rk3568-build.md)**
- **[Burning](quickstart-ide-standard-running-rk3568-burning.md)**
- **[Running](quickstart-ide-standard-running-rk3568-running.md)**
# Running a Hello World Program
- **[Hi3516 Development Board](quickstart-ide-standard-running-hi3516.md)**
- **[RK3568 Development Board](quickstart-ide-standard-running-rk3568.md)**
# Obtaining Source Code
In the Ubuntu environment, perform the following steps to obtain the OpenHarmony source code:
## Before You Start
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
3. Install the git client and git-lfs.
Update the software source:
```
sudo apt-get update
```
Run the following command to install the tools:
```
sudo apt-get install git git-lfs
```
4. Configure user information.
```
git config --global user.name "yourname"
git config --global user.email "your-email-address"
git config --global credential.helper store
```
5. Run the following commands to install the **repo** tool:
```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
```
## Obtaining Source Code
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master 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'
```
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'
```
- **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../../release-notes/Readme.md).
## Running prebuilts
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
```
# Appendix
- **[Introduction to Development Boards](quickstart-lite-board-introduction.md)**
- **[Reference](quickstart-lite-reference.md)**
# Introduction to Development Boards
- **[Introduction to the Hi3861 Development Board](quickstart-lite-introduction-hi3861.md)**
- **[Introduction to the Hi3516 Development Board](quickstart-lite-introduction-hi3516.md)**
# FAQs<a name="EN-US_TOPIC_0000001128470858"></a> # FAQs
## What should I do if garbled characters and segmentation faults occur during hb installation?<a name="section411894616119"></a>
- **Symptom**
Garbled characters and segmentation faults occur during the execution of the **python3 -m pip install --user ohos-build** command. - **[Fixing hb Installation Issues](quickstart-lite-faq-hb.md)**
- **Possible Causes**
pip is of an early version.
- **Solutions**
Upgrade pip.
```
python3 -m pip install -U pip
```
## What should I do if the message "cannot import 'sysconfig' from 'distutils'" is displayed during hb installation?<a name="section629417571626"></a>
- **Symptom**
The message "cannot import 'sysconfig' from 'distutils'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
The **distutils** module is unavailable.
- **Solutions**
Install **distutils**.
```
sudo apt-get install python3.8-distutils
```
## What should I do if the message "module 'platform' has no attribute 'linux\_distribution'" is displayed during hb installation?<a name="section10871523332"></a>
- **Symptom**
The message "module 'platform' has no attribute 'linux\_distribution'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
There is a compatibility issue of python3-pip.
- **Solutions**
Reinstall pip.
```
sudo apt remove python3-pip
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
```
## What should I do if the message "Could not find a version that satisfies the requirement ohos-build" is displayed during hb installation?<a name="section47351657163213"></a>
- **Symptom**
The message "Could not find a version that satisfies the requirement ohos-build" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
The installation fails due to poor network connectivity.
- **Solutions**
1. Ensure that your computer has a good network connection. If the network connection is unstable, rectify the network fault and reinstall hb.
2. If the network is functional, run the following commands to install hb by specifying a temporary PyPI source:
```
python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ohos-build
```
## What should I do if the message "ImportError: No module named apt\_pkg" is displayed during the execution of an unidentifiable command?<a name="section159891252236"></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.
- **Solutions**
Reinstall python3-apt.
```
sudo apt-get remove python3-apt
sudo apt-get install python3-apt
```
- **[Fixing Compilation Issues](quickstart-lite-faq-compose.md)**
- **[Fixing Burning Issues](quickstart-lite-faq-burning.md)**
# Environment Setup<a name="EN-US_TOPIC_0000001128311058"></a> # Setting Up Environments for the Mini and Small Systems
- **[Overview](quickstart-lite-env-setup-overview.md)**
- **[Setting Up Windows Development Environment](quickstart-lite-env-setup-windows.md)** ## System Requirements
- **[Setting Up Ubuntu Development Environment](quickstart-lite-env-setup-linux.md)** - Windows: Windows 10 (64-bit)
- **[FAQs](quickstart-lite-env-setup-faqs.md)** - Ubuntu: Ubuntu 18.04 or later; recommended memory: 16 GB or higher.
- User name: cannot contain Chinese characters
- DevEco Device Tool: 3.0 Release
## Installing Necessary Libraries and Tools
To install the necessary libraries and tools, perform the following steps.
On Ubuntu:
1. Run the following **apt-get** command:
```
sudo apt-get update && sudo apt-get install binutils binutils-dev git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib gcc-arm-linux-gnueabi libc6-dev-i386 libc6-dev-amd64 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 bc gnutls-bin python3.8 python3-pip ruby genext2fs device-tree-compiler make libffi-dev e2fsprogs pkg-config perl openssl libssl-dev libelf-dev libdwarf-dev u-boot-tools mtd-utils cpio doxygen liblz4-tool openjdk-8-jre gcc g++ texinfo dosfstools mtools default-jre default-jdk libncurses5 apt-utils wget scons python3.8-distutils tar rsync git-core libxml2-dev lib32z-dev grsync xxd libglib2.0-dev libpixman-1-dev kmod jfsutils reiserfsprogs xfsprogs squashfs-tools pcmciautils quota ppp libtinfo-dev libtinfo5 libncurses5-dev libncursesw5 libstdc++6 gcc-arm-none-eabi vim ssh locales
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The preceding command is applicable to Ubuntu 18.04. For other Ubuntu versions, modify the preceding installation command based on the installation package name. Specifically:
>
> - Python 3.8 or a later version is required. This section uses Python 3.8 as an example.
>
> - Java 8 or later is required. This section uses Java 8 as an example.
2. Set Python 3.8 as the default Python version.
Check the location of Python 3.8:
```
which python3.8
```
Change python and python3 to python3.8.
```
sudo update-alternatives --install /usr/bin/python python {python3.8 path} 1 #{Python3.8 path} is the location of Python 3.8 obtained in the previous step.
sudo update-alternatives --install /usr/bin/python3 python3 {python3.8 path} 1 #{Python3.8 path} is the location of Python 3.8 obtained in the previous step.
```
## Installing DevEco Device Tool
To remotely access the Ubuntu environment through Windows to perform operations such as burning, you need to install DevEco Device Tool on both Windows and Ubuntu.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> DevEco Device Tool is a one-stop integrated development environment (IDE) provided for developers of OpenHarmony-powered smart devices. It allows code editing, compiling, burning, and debugging. This document describes how to use DevEco Device Tool to remotely connect to the Ubuntu environment for burning and running.
### Installing DevEco Device Tool for Windows
1. Download the [DevEco Device Tool 3.0 Release](https://device.harmonyos.com/cn/ide#download) Windows edition.
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**. You are advised to install DevEco Device Tool in a non-system drive.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If you have installed DevEco Device Tool 3.0 Beta2 or earlier, the earlier version will be uninstalled before you install a new version. If the following error message is displayed during the uninstallation, click **Ignore** to continue the installation. This error does not affect the installation of the new version.
>
> ![en-us_image_0000001239275843](figures/en-us_image_0000001239275843.png)
![en-us_image_0000001270076961](figures/en-us_image_0000001270076961.png)
4. When prompted, select the tools to be automatically installed.
1. On the **VSCode installation confirm** page, select **Install VScode 1.62.2 automatically** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Visual Studio Code 1.62 or later has been installed, this step will be skipped.
![en-us_image_0000001237801283](figures/en-us_image_0000001237801283.png)
2. On the displayed **Python select page**, select **Download from Huawei mirror** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Python 3.8 or 3.9 has been installed, select **Use one of compatible on your PC**.
![en-us_image_0000001193983334](figures/en-us_image_0000001193983334.png)
5. In the dialog box shown below, click **Next** to download and install the tools..
![en-us_image_0000001239634067](figures/en-us_image_0000001239634067.png)
6. Wait for the DevEco Device Tool setup wizard to automatically install DevEco Device Tool. After the installation is complete, click **Finish** to close the setup wizard.
![en-us_image_0000001239650137](figures/en-us_image_0000001239650137.png)
7. From Visual Studio Code, access the DevEco Device Tool page. Now you can conduct your development in DevEco Device Tool.
![en-us_image_0000001225760456](figures/en-us_image_0000001225760456.png)
### Installing DevEco Device Tool for Ubuntu
1. Make sure the Ubuntu shell environment is **bash**.
1. Run the following command and check whether the command output is **bash**. If the command output is not **bash**, go to step 2.
```
ls -l /bin/sh
```
![en-us_image_0000001226764302](figures/en-us_image_0000001226764302.png)
2. Start the command-line tool, run the following command, enter your password, and select **No** to set **Ubuntu shell** to **bash**.
```
sudo dpkg-reconfigure dash
```
![en-us_image_0000001243641075](figures/en-us_image_0000001243641075.png)
2. Download the [DevEco Device Tool 3.0 Release Linux version](https://device.harmonyos.com/cn/ide#download).
3. Decompress the DevEco Device Tool software package and assign permission on the folder obtained from the decompression.
1. Go to the directory where the DevEco Device Tool software package is stored and run the following command to decompress the software package. In the command, change **devicetool-linux-tool-3.0.0.400.zip** to the actual software package name.
```
unzip devicetool-linux-tool-3.0.0.400.zip
```
2. Open the folder of the decompressed software package and run the following command to grant the execute permission on the installation file. In the command, change **devicetool-linux-tool-3.0.0.400.sh** to the actual installation file name.
```
chmod u+x devicetool-linux-tool-3.0.0.400.sh
```
4. Run the following command to install DevEco Device Tool, where **devicetool-linux-tool-3.0.0.400.sh** indicates the installation file name.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> During the installation, the setup wizard automatically checks whether Python 3.8 or 3.9 is installed. If Python 3.8 or 3.9 is not installed, the setup wizard displays the "Do you want to continue?" message; enter **Y** to allow the setup wizard to automatically install Python.
```
sudo ./devicetool-linux-tool-3.0.0.400.sh
```
Wait until the "Deveco Device Tool successfully installed." message is displayed.
![en-us_image_0000001198722374](figures/en-us_image_0000001198722374.png)
## Configuring Windows to Remotely Access the Ubuntu Build Environment
### Installing the SSH Service and Obtaining the IP Address for Remote Access
1. In Ubuntu, open the Terminal tool and run the following command to install the SSH service:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the command fails to be executed and the system displays a message indicating that the openssh-server and openssh-client depend on different versions, install the openssh-client of the required version (for example, **sudo apt-get install openssh-client=1:8.2p1-4**) as prompted on the command-line interface (CLI) and run the command again to install the openssh-server.
```
sudo apt-get install openssh-server
```
2. Run the following command to start the SSH service:
```
sudo systemctl start ssh
```
3. Run the following command to obtain the IP address of the current user for remote access to the Ubuntu environment from Windows:
```
ifconfig
```
![en-us_image_0000001215737140](figures/en-us_image_0000001215737140.png)
### Installing Remote SSH
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001239080359](figures/en-us-cn_image_0000001239080359.png), and search for **remote-ssh** in the Extension Marketplace.
![en-us_image_0000001193920448](figures/en-us_image_0000001193920448.png)
2. Click **Install** to install Remote-SSH. After the installation is successful, **Remote-SSH** is displayed on the **INSTALLED** list.
![en-us_image_0000001238880335](figures/en-us_image_0000001238880335.png)
### Remotely Connecting to the Ubuntu Environment
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001238760373](figures/en-us_image_0000001238760373.png), and click + on the **REMOTE EXOPLORER** page.
![en-us_image_0000001215878922](figures/en-us_image_0000001215878922.png)
2. In the **Enter SSH Connection Command** text box, enter **ssh *username@ip_address***, where *ip_address* indicates the IP address of the remote computer to be connected and *username* indicates the account name used for logging in to the remote computer.
![en-us_image_0000001215879750](figures/en-us_image_0000001215879750.png)
3. In the displayed dialog box, select the default first option as the SSH configuration file.
![en-us_image_0000001260519729](figures/en-us_image_0000001260519729.png)
4. Under **SSH TARGETS**, find the remote computer and click ![en-us_image_0000001194080414](figures/en-us_image_0000001194080414.png) to start it.
![en-us_image_0000001215720398](figures/en-us_image_0000001215720398.png)
5. In the displayed dialog box, select **Linux**, select **Continue**, and enter the password for logging in to the remote computer.
![en-us_image_0000001215897530](figures/en-us_image_0000001215897530.png)
After the connection is successful, the plug-in is automatically installed in the .vscode-server folder on the remote computer. After the installation is complete, reload Visual Studio Code in Windows as prompted. Then you can develop, compile, and burn source code in DevEco Device Tool on Windows.
### Registering the Public Key for Accessing the Ubuntu Environment
After the preceding operations are complete, you can remotely connect to the Ubuntu environment through Windows for development. However, you need to frequently enter the remote connection password. To eliminate this need, you can use the SSH public key.
1. Open the Git bash CLI and run the following command to generate an SSH public key. During command execution, perform operations as prompted. Set **username** and **ip** to the user name and IP address you use for connecting to the Ubuntu system.
```
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip
```
![en-us_image_0000001271532317](figures/en-us_image_0000001271532317.png)
2. In Visual Studio Code, click the remote connection setting button and open the **config** file.
![en-us_image_0000001226034634](figures/en-us_image_0000001226034634.png)
3. In the **config** file, add the SSK key file information, as shown below. Then save the file.
![en-us_image_0000001270356233](figures/en-us_image_0000001270356233.png)
## Obtaining Source Code
In the Ubuntu environment, perform the following steps to obtain the OpenHarmony source code:
### Preparations
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
3. Install the git client and git-lfs. (Skip this step if these tools have been installed in Installing Required Libraries and Tools. )
Update the software source:
```
sudo apt-get update
```
Run the following command to install the tools:
```
sudo apt-get install git git-lfs
```
4. Configure user information.
```
git config --global user.name "yourname"
git config --global user.email "your-email-address"
git config --global credential.helper store
```
5. Run the following commands to install the **repo** tool:
```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
```
### Obtaining Source Code
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master 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'
```
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'
```
- **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../../release-notes/Readme.md).
### Running prebuilts
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
```
## Installing the Compilation Tool
For details about the functions of the OpenHarmony compilation and building module, see [Compilation and Building Guidelines](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-build.md).
Perform the following steps in Ubuntu:
### Install hb.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> To install a proxy, see [Configuring a Proxy](../quick-start/quickstart-lite-reference.md#configuring-a-proxy).
1. Run the following command to install hb and update it to the latest version:
```
pip3 install --user build/lite
```
2. Set the environment variable.
```
vim ~/.bashrc
```
Copy the following command to the last line of the .bashrc file, save the file, and exit.
```
export PATH=~/.local/bin:$PATH
```
Update the environment variable.
```
source ~/.bashrc
```
3. Run the **hb -h** command in the source code directory. If the following information is displayed, the installation is successful:
```
usage: hb
OHOS build system
positional arguments:
{build,set,env,clean}
build Build source code
set OHOS build settings
env Show OHOS build env
clean Clean output
optional arguments:
-h, --help show this help message and exit
```
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> - Run the following command to uninstall hb:
>
> ```
> pip3 uninstall ohos-build
> ```
>
> - If any issue occurs during the hb installation, see [FAQs](../quick-start/quickstart-lite-faq-hb.md) to troubleshoot.
### Install LLVM. This step is only required for OpenHarmony_v1.x.
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> When downloading source code under the OpenHarmony_v1.x branches or tags, perform the operation procedure described in this section to install LLVM 9.0.0.
>
> When downloading source code under the Master or non-OpenHarmony_v1.x branches or tags, skip this section. hb will automatically download the latest version of LLVM.
1. Start a Linux server.
2. [Download LLVM](https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar)
3. Decompress the LLVM installation package to **~/llvm**.
```
tar -zxvf llvm.tar -C ~/
```
4. Set the environment variable.
```
vim ~/.bashrc
```
Copy the following command to the last line of the .bashrc file, save the file, and exit.
```
export PATH=~/llvm/bin:$PATH
```
5. Validate the environment variable.
```
source ~/.bashrc
```
# Fixing Burning Issues
## What should I do if Error: Opening COMxx: Access denied is displayed when I start burning
- **Symptom**
Error: Opening COMxx: Access denied is displayed after clicking Burn and selecting a serial port.
**Figure 1** Failed to open the serial port
![en-us_image_0000001226634728](figures/en-us_image_0000001226634728.png)
- **Possible Causes**
The serial port is in use.
- **Solution**
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 in use
![en-us_image_0000001226954644](figures/en-us_image_0000001226954644.png)
2. Click the dustbin icon as shown below to disable the terminal using the serial port.
**Figure 3** Disabling the terminal using the serial port
![en-us_image_0000001271234761](figures/en-us_image_0000001271234761.png)
3. Click **Burn**, select the serial port, and start burning images again.
**Figure 4** Restarting the burning task
![en-us_image_0000001271594765](figures/en-us_image_0000001271594765.png)
## What should I do when Windows-based PC failed to be connected to the board?
- **Symptom**
The file image cannot be obtained after clicking Burn and selecting a serial port.
**Figure 5** Failed to obtain the file image due to network disconnection
![en-us_image_0000001271234757](figures/en-us_image_0000001271234757.png)
- **Possible Causes**
The board is disconnected from the Windows-based PC.
Windows Firewall does not allow Visual Studio Code to access the network.
- **Solution**
1. Check whether the network cable is properly connected.
2. Click **Windows Firewall**.
**Figure 6** Network and firewall settings
![en-us_image_0000001226634732](figures/en-us_image_0000001226634732.png)
3. Click **Firewall & network protection**, and on the displayed page, click **Allow an app through the firewall**.
**Figure 7** Firewall & network protection
![en-us_image_0000001271354749](figures/en-us_image_0000001271354749.png)
4. Select Visual Studio Code.
**Figure 8** Selecting Visual Studio Code
![en-us_image_0000001271234765](figures/en-us_image_0000001271234765.png)
5. Select the **Private** and **Public** network access rights for Visual Studio Code.
**Figure 9** Allowing Visual Studio Code to access the network
![en-us_image_0000001271474585](figures/en-us_image_0000001271474585.png)
## What should I do when the image failed to be burnt?
- **Symptom**
The burning status is not displayed after clicking Burn and selecting a serial port.
- **Possible Causes**
The IDE is not restarted after the DevEco plug-in is installed.
- **Solution**
Restart the IDE.
## What should I do if no information is displayed through the serial port? (Hi3516)
- **Symptom**
The serial port shows that the connection has been established. After the board is restarted, nothing is displayed when you press **Enter**.
- **Possible Cause 1**
The serial port is connected incorrectly.
- **Solution**
Change the serial port number.
Open Device Manager to check whether the serial port connected to the board is the same as the serial port connected to the terminal. If they are different, change the serial port number by following the instructions provided in " Error: Opening COMxx: Access denied".
- **Possible Cause 2**
The U-Boot of the board is damaged.
- **Solution**
Burn the U-Boot.
If the fault persists after you perform the preceding operations, the U-Boot of the board may be damaged. You can burn the U-Boot by performing the following steps:
1. Obtain the U-Boot file.
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> The U-Boot file of the two boards can be obtained from the following paths, respectively.
>
> Hi3516D V300: device\hisilicon\hispark_taurus\sdk_liteos\uboot\out\boot\u-boot-hi3516dv300.bin
>
> Hi3518E V300: device\hisilicon\hispark_aries\sdk_liteos\uboot\out\boot\u-boot-hi3518ev300.bin
2. Burn the U-Boot file by following the procedures for burning a U-Boot file over USB.
Select the U-Boot files of corresponding development boards for burning by referring to [Burning to Hi3516D V300](https://device.harmonyos.com/en/docs/documentation/guide/ide-hi3516-upload-0000001052148681)/[Burning to Hi3518E V300](https://device.harmonyos.com/en/docs/documentation/guide/ide-hi3518-upload-0000001057313128#section93591711580).
3. Log in to the serial port after the burning is complete.
**Figure 10** Information displayed through the serial port after the U-Boot file is burnt
![en-us_image_0000001271234753](figures/en-us_image_0000001271234753.png)
# Fixing Compilation Issues
## What should I do if the message "ImportError: No module named apt_pkg" is displayed during the execution of an unidentifiable command?
- **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.
- **Solution**
Reinstall python3-apt.
```
sudo apt-get remove python3-apt
sudo apt-get install python3-apt
```
## What should I do if the message indicating Python cannot be found is displayed during compilation and building?
- **Symptom**
The following error occurs during compilation and building:
```
-bash: /usr/bin/python: No such file or directory
```
- **Possible Cause 1**
Python is not installed.
- **Solution**
Run the following command to install Python. The following uses Python 3.8 as an example.
```
sudo apt-get install python3.8
```
- **Possible Cause 2**
The soft link that points to the Python does not exist in the **usr/bin** directory.
![en-us_image_0000001271354745](figures/en-us_image_0000001271354745.png)
- **Solution**
Run the following commands to add a soft link:
```
# cd /usr/bin/
# which python3
# ln -s /usr/local/bin/python3 python
# python --version
```
Example:
![en-us_image_0000001227114636](figures/en-us_image_0000001227114636.png)
## What should I do if the message indicating Python 3 cannot be found is displayed during compilation and building?
- **Symptom**
![en-us_image_0000001227114640](figures/en-us_image_0000001227114640.png)
- **Possible Causes**
Python 3 is not installed.
- **Solution**
Run the following command to install Python 3:
```
sudo apt-get install python3.8
```
## What should I do if the message "configure: error: no acceptable C compiler found in $PATH" is displayed during Python 3 installation?
- **Symptom**
The following error occurs during Python 3 installation:
```
configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details
```
- **Possible Causes**
**gcc** is not installed.
- **Solution**
1. Run the **apt-get install gcc** command to install **gcc** online.
2. After the installation, reinstall Python 3.
## What should I do if the message "-bash: make: command not found is displayed" during Python 3 installation?
- **Symptom**
The following error occurs during Python 3 installation:
```
-bash: make: command not found
```
- **Possible Causes**
Make is not installed.
- **Solution**
1. Run the **apt-get install make** command to install Make online.
2. After the installation, reinstall Python 3.
## What should I do if the message "No module named '_ctypes'" is displayed during Python 3 installation?
- **Symptom**
The following error occurs during Python 3 installation:
```
ModuleNotFoundError: No module named '_ctypes'
```
- **Possible Causes**
**libffi** and **libffi-devel** are not installed.
- **Solution**
1. Run the **apt-get install libffi* -y** command to install **libffi** and **libffi-devel** online.
2. After the installation, reinstall Python 3.
## What should I do if the message "No module named 'Crypto'" is displayed during the build process?
- **Symptom**
The following error occurs during compilation and building:
```
ModuleNotFoundError: No module named 'Crypto'
```
- **Possible Causes**
**Crypto** is not installed.
- **Solution**
Solution 1: Run the **pip3 install Crypto** command to install **Crypto** online.
Method 2: Offline installation
Download the source code from [PyPI](https://pypi.org/project/pycrypto/#files).
![en-us_image_0000001226794696](figures/en-us_image_0000001226794696.png)
Save the source package to the Linux server, decompress the package, and run the **python3 setup.py install** command to install Crypto.
After the preceding installation is complete, rebuild an environment.
## What should I do if the message "No module named 'ecdsa'" is displayed during the build process? (Hi3861)
- **Symptom**
The following error occurs during compilation and building:
```
ModuleNotFoundError: No module named 'ecdsa'
```
- **Possible Causes**
**ecdsa** is not installed.
- **Solution**
Solution 1: Run the **pip3 install ecdsa** command to install **ecdsa** online.
Method 2: Offline installation
Download the installation package from [PyPI](https://pypi.org/project/ecdsa/#files).
![en-us_image_0000001271594753](figures/en-us_image_0000001271594753.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.
After the preceding installation is complete, rebuild an environment.
## What should I do if the message "Could not find a version that satisfies the requirement six>=1.9.0" is displayed during the build process? (Hi3861)
- **Symptom**
The following error occurs during compilation and building:
```
Could not find a version that satisfies the requirement six>=1.9.0
```
- **Possible Causes**
**six** is not installed.
- **Solution**
Solution 1: Run the **pip3 install six** command to install **six** online.
Method 2: Offline installation
Download the installation package from [PyPI](https://pypi.org/project/six/#files).
![en-us_image_0000001271474573](figures/en-us_image_0000001271474573.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**.
After the preceding installation is complete, rebuild an environment.
## What should I do if the message "cannot find -lgcc" is displayed during the build process? (Hi3861)
- **Symptom**
The following error occurs during compilation and building:
```
riscv32-unknown-elf-ld: cannot find -lgcc
```
- **Possible Causes**
The PATH is incorrectly written by **gcc_riscv32**. There is an extra slash (/).
```
~/gcc_riscv32/bin/:/data/toolchain/
```
- **Solution**
Modify the PATH by deleting the slash (/).
```
~/gcc_riscv32/bin:/data/toolchain/
```
## What should I do if an lsb_release error occurs during kconfiglib installation? (Hi3861)
- **Symptom**
The following error occurs during **kconfiglib** installation:
```
subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1.
```
- **Possible Causes**
The Python version matched with the **lsb_release** module is different from the current Python version.
- **Solution**
Run the **find / -name lsb_release** command, for example, **sudo rm -rf /usr/bin/lsb_release** to locate and delete **lsb_release**.
# Fixing hb Installation Issues
## What should I do if garbled characters and segmentation faults occur during hb installation?
- **Symptom**
Garbled characters and segmentation faults occur during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
pip is of an early version.
- **Solution**
Upgrade pip.
```
python3 -m pip install -U pip
```
## What should I do if the message "cannot import 'sysconfig' from 'distutils'" is displayed during hb installation?
- **Symptom**
The message "cannot import 'sysconfig' from 'distutils'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
The **distutils** module is unavailable.
- **Solution**
Install distutils.
```
sudo apt-get install python3.8-distutils
```
## What should I do if the message "module 'platform' has no attribute 'linux_distribution'" is displayed during hb installation?
- **Symptom**
The message "module 'platform' has no attribute 'linux_distribution'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
There is a compatibility issue of python3-pip.
- **Solution**
Reinstall pip.
```
sudo apt remove python3-pip
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
```
## What should I do if the message "Could not find a version that satisfies the requirement ohos-build" is displayed during hb installation?
- **Symptom**
The message "Could not find a version that satisfies the requirement ohos-build" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
The installation fails due to poor network connectivity.
- **Solution**
1. Ensure that your computer has a good network connection. If the network connection is unstable, rectify the network fault and reinstall hb.
2. If the network is functional, run the following commands to install hb by specifying a temporary PyPI source:
```
python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ohos-build
```
## Getting Started with Mini and Small Systems (IDE Mode)
- [Mini and Small System Overview](quickstart-ide-lite-overview.md)
- Environment Preparation
- [Setting Up the Windows+Ubuntu Hybrid Build Environment](quickstart-ide-lite-env-setup-win-ubuntu.md)
- [Obtaining Source Code](quickstart-ide-lite-sourcecode-acquire.md)
- [Creating a Source Code Project](quickstart-ide-lite-create-project.md)
- Running a Hello World Program
- Hi3861 Development Board
- [Writing a Hello World Program](quickstart-ide-lite-steps-hi3861-application-framework.md)
- [Building](quickstart-ide-lite-steps-hi3861-building.md)
- [Burning](quickstart-ide-lite-steps-hi3861-burn.md)
- [Networking](quickstart-ide-lite-steps-hi3861-netconfig.md)
- [Debugging and Verification](quickstart-ide-lite-steps-hi3861-debug.md)
- [Running](quickstart-ide-lite-steps-hi3816-running.md)
- Hi3516 Development Board
- [Writing a Hello World Program](quickstart-ide-lite-steps-hi3516-application-framework.md)
- [Building](quickstart-ide-lite-steps-hi3516-building.md)
- [Burning](quickstart-ide-lite-steps-hi3516-burn.md)
- [Running](quickstart-ide-lite-steps-hi3516-running.md)
- Appendix
- Introduction to Development Boards
- [Introduction to the Hi3861 Development Board](quickstart-ide-lite-introduction-hi3861.md)
- [Introduction to the Hi3516 Development Board](quickstart-ide-lite-introduction-hi3516.md)
- [Getting Started with Mini and Small Systems (Installation Package Mode)](quickstart-lite-package-directory.md)
# Hi3516 Development Board<a name="EN-US_TOPIC_0000001174350603"></a> # Introduction to the Hi3516 Development Board
## Introduction<a name="section26131214194212"></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 1** Hi3516D V300 front view<a name="fig6340825506"></a>
![](figures/hi3516d-v300-front-view.png "hi3516d-v300-front-view")
## Development Board Specifications<a name="section15192203316533"></a>
**Table 1** Specifications of the Hi3516 development board
<a name="table31714894311"></a>
<table><thead align="left"><tr id="row10171198194310"><th class="cellrowborder" valign="top" width="14.77%" id="mcps1.2.3.1.1"><p id="a2b235e9ed55f4338886788f140e648a0"><a name="a2b235e9ed55f4338886788f140e648a0"></a><a name="a2b235e9ed55f4338886788f140e648a0"></a>Type</p>
</th>
<th class="cellrowborder" valign="top" width="85.22999999999999%" id="mcps1.2.3.1.2"><p id="p9702458104014"><a name="p9702458104014"></a><a name="p9702458104014"></a>Specification</p>
</th>
</tr>
</thead>
<tbody><tr id="row0171168114311"><td class="cellrowborder" valign="top" width="14.77%" headers="mcps1.2.3.1.1 "><p id="p1698185431418"><a name="p1698185431418"></a><a name="p1698185431418"></a>Processor and internal memory</p>
</td>
<td class="cellrowborder" valign="top" width="85.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul1147113537186"></a><a name="ul1147113537186"></a><ul id="ul1147113537186"><li>Hi3516D V300</li><li>DDR3 1GB</li><li>8 GB eMMC4.5</li></ul>
</td>
</tr>
<tr id="row21721687435"><td class="cellrowborder" valign="top" width="14.77%" headers="mcps1.2.3.1.1 "><p id="p817216810435"><a name="p817216810435"></a><a name="p817216810435"></a>External components</p>
</td>
<td class="cellrowborder" valign="top" width="85.22999999999999%" headers="mcps1.2.3.1.2 "><a name="ul179543016208"></a><a name="ul179543016208"></a><ul id="ul179543016208"><li>Ethernet port</li><li>Audio and video<a name="ul5941311869"></a><a name="ul5941311869"></a><ul id="ul5941311869"><li>One voice input</li><li>One mono (AC_L) output, connected to a 3 W power amplifier (LM4871)</li><li>MicroHDMI (one HDMI 1.4)</li></ul>
</li><li>Camera<a name="ul924263620"></a><a name="ul924263620"></a><ul id="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="ul101471711667"></a><a name="ul101471711667"></a><ul id="ul101471711667"><li>2.35-inch LCD connector</li><li>5.5-inch LCD connector</li></ul>
</li><li>External components and interfaces<a name="ul089255556"></a><a name="ul089255556"></a><ul id="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>USB2.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>
</li></ul>
</td>
</tr>
</tbody>
</table>
## Overview
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** Hi3516 front view
![en-us_image_0000001227082182](figures/en-us_image_0000001227082182.png)
## Development Board Specifications
**Table 1** Hi3516 specifications
| Item| Description|
| -------- | -------- |
| Processor and internal memory| -&nbsp;Hi3516D V300 chip<br>-&nbsp;DDR3&nbsp;1GB<br>-&nbsp;eMMC 4.5, 8 GB capacity|
| External components| -&nbsp;Ethernet port<br>-&nbsp;Audio and video<br>&nbsp;&nbsp;-&nbsp;1 voice input<br>&nbsp;&nbsp;-&nbsp;1 mono channel (AC_L) output, connected to a 3 W power amplifier (LM4871)<br>&nbsp;&nbsp;-&nbsp;MicroHDMI (1-channel HDMI 1.4)<br>-&nbsp;Camera<br>&nbsp;&nbsp;-&nbsp;Sensor IMX335<br>&nbsp;&nbsp;-&nbsp;M12 lens, 4 mm focal length, and 1.8 aperture<br>-&nbsp;Display<br>&nbsp;&nbsp;-&nbsp;LCD connector (2.35-inch)<br>&nbsp;&nbsp;-&nbsp;LCD connector (5.5-inch)<br>-&nbsp;External components and ports<br>&nbsp;&nbsp;-&nbsp;Memory card port<br>&nbsp;&nbsp;-&nbsp;JTAG/I2S port<br>&nbsp;&nbsp;-&nbsp;ADC port<br>&nbsp;&nbsp;-&nbsp;Steering gear port<br>&nbsp;&nbsp;-&nbsp;Grove connector<br>&nbsp;&nbsp;-&nbsp;USB 2.0 (Type-C)<br>&nbsp;&nbsp;-&nbsp;Three function keys, two user-defined keys, and one upgrade key<br>&nbsp;&nbsp;-&nbsp;LED indicator, green or red|
# Hi3861 Development Board<a name="EN-US_TOPIC_0000001174270685"></a> # Introduction to the Hi3861 Development Board
## Introduction<a name="section19352114194115"></a>
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>
![](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>
![](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.
- The Hi3861 chip integrates the high-performance 32-bit microprocessor, hardware security engine, and various peripheral interfaces. The peripheral interfaces include the Synchronous Peripheral Interface \(SPI\), Universal Asynchronous Receiver & Transmitter \(UART\), the Inter Integrated Circuit \(I2C\), Pulse Width Modulation \(PWM\), General Purpose Input/Output \(GPIO\) interface, and Analog to Digital Converter \(ADC\). The Hi3861 chip also supports the high-speed Secure Digital Input/Output \(SDIO\) 2.0 interface, with a maximum clock frequency of 50 MHz. This chip has a built-in static random access memory \(SRAM\) and flash memory, so that programs can run independently or run from a flash drive.
- The Hi3861 chip applies to Internet of Things \(IoT\) devices such as smart home appliances.
**Figure 3** Hi3861 functions<a name="fig1367035113590"></a>
![](figures/hi3861-functions.png "hi3861-functions")
## Resources and Constraints<a name="section82610215014"></a>
As the Hi3861 only offers 2 MB Flash and 352 KB RAM, use them efficiently when compiling code.
## Development Board Specifications<a name="section169054431017"></a>
**Table 1** Hi3861 WLAN module specifications
<a name="t672b053e2ac94cbdb5244857fed4764e"></a>
<table><thead align="left"><tr id="r54b3810e43d24e1887c1d6a41394996b"><th class="cellrowborder" valign="top" width="18.060000000000002%" id="mcps1.2.3.1.1"><p id="a2b235e9ed55f4338886788f140e648a0"><a name="a2b235e9ed55f4338886788f140e648a0"></a><a name="a2b235e9ed55f4338886788f140e648a0"></a>Type</p>
</th>
<th class="cellrowborder" valign="top" width="81.94%" id="mcps1.2.3.1.2"><p id="a95c4ba2e404f4a45b65984746aaa56ab"><a name="a95c4ba2e404f4a45b65984746aaa56ab"></a><a name="a95c4ba2e404f4a45b65984746aaa56ab"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="r71f534ea66af4191b020408df5978f41"><td class="cellrowborder" valign="top" width="18.060000000000002%" headers="mcps1.2.3.1.1 "><p id="a0531f1bb62d5443880576cc5de23f2e6"><a name="a0531f1bb62d5443880576cc5de23f2e6"></a><a name="a0531f1bb62d5443880576cc5de23f2e6"></a>General specifications</p>
</td>
<td class="cellrowborder" valign="top" width="81.94%" headers="mcps1.2.3.1.2 "><a name="u2a0d06f28d454d30818ced9a0432211b"></a><a name="u2a0d06f28d454d30818ced9a0432211b"></a><ul id="u2a0d06f28d454d30818ced9a0432211b"><li>Operates over 1×1 2.4 GHz frequency band (ch1-ch14).</li><li>The physical layer (PHY) complies with the IEEE 802.11b/g/n protocol.</li><li>The media access control (MAC) layer complies with the IEEE802.11 d/e/h/i/k/v/w protocol.</li></ul>
<a name="u8f31d142d92147789195a18b50836d2c"></a><a name="u8f31d142d92147789195a18b50836d2c"></a><ul id="u8f31d142d92147789195a18b50836d2c"><li>Includes the built-in public address (PA) and local area network (LAN); integrates transmit-receive (Tx/Rx) switch and Balun. </li><li>Supports the station (STA) and access point (AP) modes. When the Hi3861 WLAN module functions as an AP, a maximum of six STAs are supported.</li><li>Supports WFA WPA, WFA WPA2 personal, and WPS2.0.</li><li>Supports three kinds of packet traffic arbiter (PTA) (2- , 3- , or 4-wire PTA), each of which coexists with the BT or BLE chip.</li><li>The input voltage ranges from 2.3 V to 3.6 V.</li></ul>
<a name="ul114549122110"></a><a name="ul114549122110"></a><ul id="ul114549122110"><li>The input/output (I/O) power voltage can be 1.8 V or 3.3 V.</li></ul>
<a name="ue044275c53b84dd29dda674e16e72823"></a><a name="ue044275c53b84dd29dda674e16e72823"></a><ul id="ue044275c53b84dd29dda674e16e72823"><li>Supports self-calibration for RF hardware.</li><li>Performs with low power consumption:<a name="ul0879143622219"></a><a name="ul0879143622219"></a><ul id="ul0879143622219"><li>Ultra deep sleep mode: 5 μA @ 3.3 V</li><li>DTIM1: 1.5 mA @ 3.3 V</li><li>DTIM3: 0.8 mA @ 3.3 V</li></ul>
</li></ul>
</td>
</tr>
<tr id="rd9b56e759af34950b6887ca1bf5bb7cf"><td class="cellrowborder" valign="top" width="18.060000000000002%" headers="mcps1.2.3.1.1 "><p id="a0aed3860a78a4b50bedf60699afd3996"><a name="a0aed3860a78a4b50bedf60699afd3996"></a><a name="a0aed3860a78a4b50bedf60699afd3996"></a>PHY features</p>
</td>
<td class="cellrowborder" valign="top" width="81.94%" headers="mcps1.2.3.1.2 "><a name="u6568aa052152432aa1f44372445ca634"></a><a name="u6568aa052152432aa1f44372445ca634"></a><ul id="u6568aa052152432aa1f44372445ca634"><li>Supports all data rates of the single antenna required by the IEEE802.11b/g/n protocol.</li><li>Supports a maximum rate of 72.2 Mbps@HT20 MCS7</li><li>Supports the standard bandwidth (20 MHz) and narrow bandwidth (5 MHz or 10 MHz).</li><li>Supports space-time block coding (STBC).</li><li>Supports short guard interval (Short-GI).</li></ul>
</td>
</tr>
<tr id="r3563f9df9759486794952d46c5d2d03f"><td class="cellrowborder" valign="top" width="18.060000000000002%" headers="mcps1.2.3.1.1 "><p id="afd48a2d879dc4aada8b60bebb96523c7"><a name="afd48a2d879dc4aada8b60bebb96523c7"></a><a name="afd48a2d879dc4aada8b60bebb96523c7"></a>MAC features</p>
</td>
<td class="cellrowborder" valign="top" width="81.94%" headers="mcps1.2.3.1.2 "><a name="uca57d799e7814925a5bf1b891335bd79"></a><a name="uca57d799e7814925a5bf1b891335bd79"></a><ul id="uca57d799e7814925a5bf1b891335bd79"><li>Supports aggregate MAC service data unit (A-MPDU) and aggregate MAC protocol data unit (A-MSDU). </li><li>Supports block acknowledgment (Blk-ACK).</li><li>Supports quality of service (QoS), meeting customer's service requirements.</li></ul>
</td>
</tr>
<tr id="r3e1c86e5f6cd4df0a1b30a08fb8481a2"><td class="cellrowborder" valign="top" width="18.060000000000002%" headers="mcps1.2.3.1.1 "><p id="a57086ea97a1b46cdb21953bf0fc22d94"><a name="a57086ea97a1b46cdb21953bf0fc22d94"></a><a name="a57086ea97a1b46cdb21953bf0fc22d94"></a>CPU subsystem</p>
</td>
<td class="cellrowborder" valign="top" width="81.94%" headers="mcps1.2.3.1.2 "><a name="u612cc2cd0cfe40229263c4f506c0c69c"></a><a name="u612cc2cd0cfe40229263c4f506c0c69c"></a><ul id="u612cc2cd0cfe40229263c4f506c0c69c"><li>Integrates a high-performance 32-bit microprocessor with a maximum operating frequency of 160 MHz.</li><li>Includes built-in 352 KB SRAM and 288 KB ROM.</li><li>Includes a built-in 2 MB flash memory.</li></ul>
</td>
</tr>
<tr id="rae93c5236b084cd2a2c0d5c29027b40e"><td class="cellrowborder" valign="top" width="18.060000000000002%" headers="mcps1.2.3.1.1 "><p id="a9b14a9e95b3849278c332259d8add1b2"><a name="a9b14a9e95b3849278c332259d8add1b2"></a><a name="a9b14a9e95b3849278c332259d8add1b2"></a>Peripheral interfaces</p>
</td>
<td class="cellrowborder" valign="top" width="81.94%" headers="mcps1.2.3.1.2 "><a name="u7c73ebffd89e4092bd65f0d878d59b22"></a><a name="u7c73ebffd89e4092bd65f0d878d59b22"></a><ul id="u7c73ebffd89e4092bd65f0d878d59b22"><li>Include one SDIO interface, two SPI interfaces, two I2C interfaces, three UART interfaces, 15 GPIO interfaces, seven ADC inputs, six PWM interfaces, and one I2S interface (Note: These interfaces are all multiplexed.)</li><li>The frequency of the external primary crystal oscillator is 40 MHz or 24 MHz.</li></ul>
</td>
</tr>
<tr id="r18810701aafe42ad8d9a7d882730c210"><td class="cellrowborder" valign="top" width="18.060000000000002%" headers="mcps1.2.3.1.1 "><p id="ae8f47db913724e458c265e858409950b"><a name="ae8f47db913724e458c265e858409950b"></a><a name="ae8f47db913724e458c265e858409950b"></a>Other information</p>
</td>
<td class="cellrowborder" valign="top" width="81.94%" headers="mcps1.2.3.1.2 "><a name="u25f28919a3b044c5af50f9f5f5616083"></a><a name="u25f28919a3b044c5af50f9f5f5616083"></a><ul id="u25f28919a3b044c5af50f9f5f5616083"><li>Package: QFN-32, 5 mm x 5 mm</li><li>Operating temperature: –40&deg;C to +85&deg;C</li></ul>
</td>
</tr>
</tbody>
</table>
## Key Features<a name="section1317173016507"></a>
OpenHarmony provides a series of available capabilities based on the Hi3861 platform. The following table describes the available key components.
**Table 2** Key components
<a name="table1659013482514"></a>
<table><thead align="left"><tr id="row1368918486512"><th class="cellrowborder" valign="top" width="22.63%" id="mcps1.2.3.1.1"><p id="p668914812516"><a name="p668914812516"></a><a name="p668914812516"></a>Component</p>
</th>
<th class="cellrowborder" valign="top" width="77.37%" id="mcps1.2.3.1.2"><p id="p9689154855115"><a name="p9689154855115"></a><a name="p9689154855115"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row868910487517"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p13689248165114"><a name="p13689248165114"></a><a name="p13689248165114"></a>wlan</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p11689144816511"><a name="p11689144816511"></a><a name="p11689144816511"></a>Provides WLAN service, such as connecting to or disconnecting from a station or hotspot, and querying the state of a station or hotspot.</p>
</td>
</tr>
<tr id="row568964819514"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p5689548175113"><a name="p5689548175113"></a><a name="p5689548175113"></a>iot controller</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p176893480517"><a name="p176893480517"></a><a name="p176893480517"></a>Provides the capability of operating peripherals, including the I2C, I2S, ADC, UART, SPI, SDIO, GPIO, PWM and FLASH.</p>
</td>
</tr>
<tr id="row143420119366"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p1737117331480"><a name="p1737117331480"></a><a name="p1737117331480"></a>soft bus</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p1037123314485"><a name="p1037123314485"></a><a name="p1037123314485"></a>Provides the capabilities of device discovery and data transmission in the distributed network.</p>
</td>
</tr>
<tr id="row1383559163617"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p2379233113914"><a name="p2379233113914"></a><a name="p2379233113914"></a>hichainsdk</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p5809349205012"><a name="p5809349205012"></a><a name="p5809349205012"></a>Provides the capability of securely transferring data between devices when they are interconnected.</p>
</td>
</tr>
<tr id="row54428163612"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p3775133619587"><a name="p3775133619587"></a><a name="p3775133619587"></a>huks</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p11304151710555"><a name="p11304151710555"></a><a name="p11304151710555"></a>Provides capabilities of key management, encryption, and decryption.</p>
</td>
</tr>
<tr id="row12690548135110"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p176901648115111"><a name="p176901648115111"></a><a name="p176901648115111"></a>system ability manager</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p1181353173111"><a name="p1181353173111"></a><a name="p1181353173111"></a>Provides a unified <span id="text10778141516322"><a name="text10778141516322"></a><a name="text10778141516322"></a>OpenHarmony</span> service development framework based on the service-oriented architecture.</p>
</td>
</tr>
<tr id="row1657310121587"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p730664220114"><a name="p730664220114"></a><a name="p730664220114"></a>bootstrap</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p39689262310"><a name="p39689262310"></a><a name="p39689262310"></a>Provides the entry identifier for starting a system service. When the system service management is started, the function identified by <strong id="b1954132834115"><a name="b1954132834115"></a><a name="b1954132834115"></a>bootstrap</strong> is called to start a system service.</p>
</td>
</tr>
<tr id="row15763812165616"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p17171118128"><a name="p17171118128"></a><a name="p17171118128"></a>syspara</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p12763912125617"><a name="p12763912125617"></a><a name="p12763912125617"></a>Provides capabilities of obtaining and setting system attributes.</p>
</td>
</tr>
<tr id="row121911343566"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p1097517270361"><a name="p1097517270361"></a><a name="p1097517270361"></a>utils</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p6848159569"><a name="p6848159569"></a><a name="p6848159569"></a>Provides basic and public capabilities, such as file operations and key-value (KV) storage management.</p>
</td>
</tr>
<tr id="row144219192579"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p8333104843714"><a name="p8333104843714"></a><a name="p8333104843714"></a>DFX</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p65111025155711"><a name="p65111025155711"></a><a name="p65111025155711"></a>Provides the DFX capabilities, such as logging and printing.</p>
</td>
</tr>
<tr id="row16159522125710"><td class="cellrowborder" valign="top" width="22.63%" headers="mcps1.2.3.1.1 "><p id="p18835202765718"><a name="p18835202765718"></a><a name="p18835202765718"></a>XTS</p>
</td>
<td class="cellrowborder" valign="top" width="77.37%" headers="mcps1.2.3.1.2 "><p id="p3835192795717"><a name="p3835192795717"></a><a name="p3835192795717"></a>Provides a set of <span id="text1482414523409"><a name="text1482414523409"></a><a name="text1482414523409"></a>OpenHarmony</span> certification test suites.</p>
</td>
</tr>
</tbody>
</table>
## Overview
Hi3861 is a 2 x 5 cm development board. It is a 2.4 GHz WLAN SoC chip that highly integrates the IEEE 802.11b/g/n baseband and radio frequency (RF) circuit. It supports OpenHarmony and provides an open and easy-to-use development and debugging environment.
**Figure 1** Hi3861 development board
![en-us_image_0000001226634692](figures/en-us_image_0000001226634692.png)
The Hi3861 development board can also be connected to the Hi3861 mother board to expand its peripheral capabilities. The following figure shows the Hi3861 mother board.
**Figure 2** Hi3861 mother board
![en-us_image_0000001226794660](figures/en-us_image_0000001226794660.png)
- 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.
- The Hi3861 chip integrates the high-performance 32-bit microprocessor, hardware security engine, and various peripheral interfaces. The peripheral interfaces include the Synchronous Peripheral Interface (SPI), Universal Asynchronous Receiver & Transmitter (UART), the Inter-Integrated Circuit (I2C), Pulse Width Modulation (PWM), General Purpose Input/Output (GPIO) interface, and Analog to Digital Converter (ADC). The Hi3861 chip also supports the high-speed Secure Digital Input/Output (SDIO) 2.0 interface, with a maximum clock frequency of 50 MHz. This chip has a built-in static random access memory (SRAM) and flash memory, so that programs can run independently or run from a flash drive.
- The Hi3861 chip applies to Internet of Things (IoT) devices such as smart home appliances.
**Figure 3** Functional block diagram of Hi3861
![en-us_image_0000001226794688](figures/en-us_image_0000001226794688.png)
## Resources and Constraints
The resources of the Hi3861 development board are limited. The entire board has a 2 MB flash memory and 352 KB RAM. When writing service code, pay attention to the resource usage efficiency.
## Development Board Specifications
**Table 1** Hi3861 specifications
| Item| Description|
| -------- | -------- |
| General specifications| -&nbsp;1 x 1 2.4 GHz frequency band (ch1–ch14)<br>-&nbsp;PHY supports IEEE 802.11b/g/n.<br>-&nbsp;MAC supports IEEE802.11d/e/h/i/k/v/w.<br>-&nbsp;Built-in PA and LNA; integrated TX/RX switch and Balun<br>-&nbsp;Support for STA and AP modes. When functioning as an AP, it supports a maximum of 6 STAs.<br>-&nbsp;Support for WFA WPA/WPA2 personal and WPS2.0.<br>-&nbsp;2/3/4-line PTA solution that coexists with BT/BLE chips.<br>-&nbsp;Input voltage range: 2.3 V to 3.6 V<br>-&nbsp;I/O power voltage: 1.8 V or 3.3 V.<br>-&nbsp;RF self-calibration<br>-&nbsp;Low power consumption:<br>&nbsp;&nbsp;-&nbsp;Ultra Deep Sleep mode: 5 μA@3.3 V<br>&nbsp;&nbsp;-&nbsp;DTIM1: 1.5 mA \@3.3V<br>&nbsp;&nbsp;-&nbsp;DTIM3: 0.8 mA \@3.3V|
| PHY features| -&nbsp;Supports all data rates of the IEEE802.11b/g/n single antenna.<br>-&nbsp;Supported maximum rate: 72.2 Mbps\@HT20&nbsp;MCS7<br>-&nbsp;20 MHz standard bandwidth and 5 MHz/10 MHz narrow bandwidth.<br>-&nbsp; STBC.<br>-&nbsp;Short-GI.|
| MAC features| -&nbsp;A-MPDU and A-MSDU.<br>-&nbsp;Blk-ACK.<br>-&nbsp;QoS to meet the quality requirements of different services.|
| CPU subsystem| - &nbsp;High-performance 32-bit microprocessor with a maximum working frequency of 160 MHz.<br>-&nbsp;Embedded SRAM of 352 KB; ROM of 288 KB<br>-&nbsp;Embedded 2 MB flash memory|
| Peripheral ports| -&nbsp;One SDIO interface, two SPI interfaces, two I2C interfaces, three UART interfaces, 15 GPIO interfaces, seven ADC inputs, six PWM interfaces, and one I2S interface (Note: These interfaces are all multiplexed.)<br>-&nbsp;Frequency of the external main crystal: 40 MHz or 24 MHz|
| Others| -&nbsp;Package: QFN-32, 5 mm x 5 mm<br>-&nbsp;Working temperature: -40°C to +85°C|
## OpenHarmony Key Features
OpenHarmony provides a wide array of available capabilities based on the Hi3861 platform. The following table describes the available key components.
**Table 2** Key components of OpenHarmony
| Component| Capability|
| -------- | -------- |
| WLAN| Provides the WLAN service capability. For example, connecting to or disconnecting from a station or hotspot, and querying the status of a station or hotspot.|
| IoT controller| Provides the capability of operating peripherals, including the I2C, I2S, ADC, UART, SPI, SDIO, GPIO, PWM and flash memory.|
| DSoftBus| Provides the capabilities of device discovery and data transmission in the distributed network.|
| hichainsdk| Provides the capability of securely transferring data between devices when they are interconnected.|
| huks| Provides capabilities of key management, encryption, and decryption.|
| System service management| Provides a unified OpenHarmony service development framework based on the service-oriented architecture.|
| Boot| Provides the entry identifier for starting a system service. When the system service management is started, the function identified by bootstrap is called to start a system service.|
| System attribute| Provides capabilities of obtaining and setting system attributes.|
| Base library| Provides the common basic library capability, including file operations and KV storage management.|
| DFX | Provides the DFX capability, such as logging and printing.|
| XTS | Provides a set of OpenHarmony certification test suites.|
# Overview<a name="EN-US_TOPIC_0000001128311060"></a> # Mini and Small System Overview
The mini and small OpenHarmony systems are suitable for IoT devices with limited memory. This document describes the system development with three typical development boards: Hi3861 WLAN module, Hi3516D V300, and Hi3518E V300.
With this document, you will quickly get familiar with environment setup, build, burning, debugging, and simple app and driver development for mini and small systems. ## Introduction
The OpenHarmony mini and small systems apply to devices with a reference memory greater than or equal to 128 KiB. This document helps you quickly get started for development of the OpenHarmony standard system, from environment setup to building, burning, and startup.
To accommodate different developer habits, OpenHarmony provides two modes for getting started with the standard system:
- IDE mode: DevEco Device Tool is used for one-stop development, covering dependency installation, building, burning, and running.
- Installation package mode: Dependency download and installation as well as building operations are performed using commands. Burning and running are performed in DevEco Device Tool. OpenHarmony also provides the [Docker environment](../get-code/gettools-acquire.md), which can significantly simplify the environment configuration before compilation. You can build your source code in the Docker environment if you are more accustomed to using the installation package mode.
This document exemplifies how to use the installation package mode. For details about the IDE mode, see [Getting Started with Mini and Small Systems (IDE Mode)](../quick-start/quickstart-lite-ide-directory.md).
## Development Environment
In the Windows+Ubuntu hybrid environment for OpenHarmony development:
- Windows: used for source code development and burning.
- Ubuntu: used for source code building.
This document describes how to develop OpenHarmony in the Windows+Ubuntu environment.
## Development Boards
In this document, two development board models are used as examples: Hi3861 and Hi3516D V300. For details about these development boards, see [Appendix](../quick-start/quickstart-lite-board-introduction.md). You can purchase the development board as required.
## Development Process
Below you can see the quick start process for the development of the mini and small systems.
**Figure 1** Quick start process for the development of the mini and small systems
![en-us_image_0000001271562257](figures/en-us_image_0000001271562257.png)
## Getting Started with Mini and Small Systems (Installation Package Mode)
- [Mini and Small System Overview](quickstart-lite-overview.md)
- [Environment Preparation](quickstart-lite-env-setup.md)
- Running a Hello World Program
- Hi3861 Development Board
- [Setting Up the Hi3861 Development Board Environment](quickstart-lite-steps-hi3861-setting.md)
- [Writing a Hello World Program](quickstart-lite-steps-hi3861-application-framework.md)
- [Building](quickstart-lite-steps-hi3861-building.md)
- [Burning](quickstart-lite-steps-hi3861-burn.md)
- [Networking](quickstart-lite-steps-hi3861-netconfig.md)
- [Debugging and Verification](quickstart-lite-steps-hi3861-debug.md)
- [Running](quickstart-lite-steps-hi3816-running.md)
- Hi3516 Development Board
- [Setting Up the Hi3516 Development Board Environment](quickstart-lite-steps-hi3516-setting.md)
- [Writing a Hello World Program](quickstart-lite-steps-hi3516-application-framework.md)
- [Building](quickstart-lite-steps-hi3516-building.md)
- [Burning](quickstart-lite-steps-hi3516-burn.md)
- [Running](quickstart-lite-steps-hi3516-running.md)
- FAQs
- [Fixing hb Installation Issues](quickstart-lite-faq-hb.md)
- [Fixing Compilation Issues](quickstart-lite-faq-compose.md)
- [Fixing Burning Issues](quickstart-lite-faq-burning.md)
- Appendix
- Introduction to Development Boards
- [Introduction to the Hi3861 Development Board](quickstart-lite-introduction-hi3861.md)
- [Introduction to the Hi3516 Development Board](quickstart-lite-introduction-hi3516.md)
- [Getting Started with Mini and Small Systems (IDE Mode)](quickstart-lite-ide-directory.md)
- [Reference](quickstart-lite-reference.md)
# Reference
## Using the build.sh Script to Build Source Code
1. Go to the root directory of the source code and run the build command.
```
./build.sh --product-name name --ccache
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> _name_ indicates the product name, for example, **Hi3516D V300** and **rk3568**.
2. Check the build result. After the build is complete, the following information is displayed in the log:
```
post_process
=====build name successful.
```
Files generated during the build are stored in the **out/{device_name}/** directory, and the generated image is stored in the **out/{device_name}/packages/phone/images/** directory.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> For details about other modular compilation operations, see [Building a Standard System](../subsystems/subsys-build-standard-large.md).
## Configuring the Proxy
### Setting Up the Python Proxy
1. Create a proxy configuration file.
```
mkdir ~/.pipvim ~/.pip/pip.conf
```
2. Add the following proxy information to the file, save the file, and exit:
```
[global]
index-url = http:// Proxy URL
trusted-host = Trusted image path
timeout = 120
```
### Setting Up the npm Proxy
1. Create a proxy configuration file.
```
vim ~/.npmrc
```
2. Add the following proxy information to the file, save the file, and exit:
```
Registry=http:// Proxy URL
strict-ssl=false
```
3. Add the following content to the **.bashrc** file, save the file, and exit:
```
export NPM_REGISTRY=http:// Proxy URL
source .bashrc
```
# Obtaining Source Code<a name="EN-US_TOPIC_0000001177086414"></a>
## Prerequisites<a name="section21887149017"></a>
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
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"
git config --global user.email "your-email-address"
git config --global credential.helper store
```
4. Run the following commands to install the **repo** tool:
```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
```
## How to Obtain<a name="section349724435812"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
>Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master 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'
```
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'
```
- **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../get-code/../../release-notes/Readme.md).
# Writing a Hello World Program
The following exemplifies how to run the first program on the development board. The created program outputs the message "Hello World!" .
## Example Directory
The complete code directory is as follows:
```
applications/sample/hello
│── BUILD.gn
└── src
└── helloworld.c
```
## How to Develop
Perform the steps below in the source code directory:
1. Create a directory and the program source code.
Create the **applications/sample/hello/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **OHOS** to **World**. You can use either C or C++ to develop a program.
```
#include <stdio.h>
int main(int argc, char **argv)
{
printf("\n\n");
printf("\n\t\tHello OHOS!\n");
printf("\n\n\n");
return 0;
}
```
2. Create a build file.
Create the **applications/sample/hello/BUILD.gn** file. The file content is as follows:
```
import("//build/lite/config/component/lite_component.gni")
lite_component("hello-OHOS") {
features = [ ":helloworld" ]
}
executable("helloworld") {
output_name = "helloworld"
sources = [ "src/helloworld.c" ]
}
```
3. Add a component.
Modify the **build/lite/components/applications.json** file and add the configuration of **hello_world_app**. The following code snippet is a snippet of the **applications.json** file: The configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"components": [
{
"component": "camera_sample_communication",
"description": "Communication related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/communication"
],
"targets": [
"//applications/sample/camera/communication:sample"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##start##
{
"component": "hello_world_app",
"description": "hello world samples.",
"optional": "true",
"dirs": [
"applications/sample/hello"
],
"targets": [
"//applications/sample/hello:hello-OHOS"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##end##
{
"component": "camera_sample_app",
"description": "Camera related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/launcher",
"applications/sample/camera/cameraApp",
"applications/sample/camera/setting",
"applications/sample/camera/gallery",
"applications/sample/camera/media"
],
```
4. Modify the board configuration file.
Modify the **vendor/hisilicon/hispark_taurus/config.json** file and add an entry of the **hello_world_app** component. The following code snippet is the configuration of the **applications** subsystem, the configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"subsystem": "applications",
"components": [
{ "component": "camera_sample_app", "features":[] },
{ "component": "camera_sample_ai", "features":[] },
##start##
{ "component": "hello_world_app", "features":[] },
##end##
{ "component": "camera_screensaver_app", "features":[] }
]
},
```
# Building
You can build source code with hb or the **build.sh** script. This section exemplifies how to build source code with hb. For details about how to build with the **build.sh** script, see [Building Source Code Using the build.sh Script](../quick-start/quickstart-lite-reference.md).
Go to the root directory of the source code and run the build command.
1. Set the build path.
```
hb set
```
2. Select the current path.
```
.
```
3. Select **ipcamera_hispark_taurus** under **hisilicon** and press **Enter**.
4. Start building.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - To build a component (for example, **hello**), run the **hb build -T _ Target name _** command.
>
> - To build a product incrementally, run the **hb build** command.
>
> - To build a product from the scratch, run the **hb build -f** command.
>
> This example builds a product from the scratch.
```
hb build -f
```
**Figure 1** Hi3516 build settings
![en-us_image_0000001271594749](figures/en-us_image_0000001271594749.png)
5. Check the build result. If "build success" is displayed, the building is successful.
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> Paths to burning-related files:
>
> - Build result and log files: **out/hispark_taurus/ipcamera_hispark_taurus**
>
> - U-Boot file: **device/board/hisilicon/hispark_taurus/uboot/out/boot/u-boot-hi3516dv300.bin**
# Burning
Hi3516D V300 supports burning through the USB port, network port, and serial port. This document describes how to burn source code through the USB port. The operations are performed in Windows.
### Importing Source Code
After the building is complete, ensure that you can [remotely access the Ubuntu environment from Windows](../quick-start/quickstart-lite-env-setup.md). Then, perform the following steps to import the source code before burning:
1. Open DevEco Device Tool, go to the home page, and click **Import Project** to open your project or source code.
![en-us_image_0000001171426014](figures/en-us_image_0000001171426014.png)
2. Select the target directory (in the Ubuntu environment) and click **Import**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Make sure the selected directory does not contain Chinese characters or spaces. Otherwise, the building may fail.
![en-us_image_0000001271791385](figures/en-us_image_0000001271791385.png)
3. If you select to open the OpenHarmony source code, a message will be displayed indicating that the project is not a DevEco Device Tool project. Click **Import** to continue.
![en-us_image_0000001135394334](figures/en-us_image_0000001135394334.png)
4. On the **Select Project type** page, select **Import from OpenHarmony Source**.
![en-us_image_0000001215743910](figures/en-us_image_0000001215743910.png)
5. On the **Import Project** page, select a product, and the MCU, board, company, and kernel fields will be automatically populated. Then, select the OpenHarmony source code version for **ohosVersion**. Select **ipcamera_hispark_taurus**.
![en-us_image_0000001227711014](figures/en-us_image_0000001227711014.png)
6. Click **Open** to open the project or source code.
### Burning
After the source code is imported, perform the following steps:
1. Connect the computer and the target development board through the serial port and USB port. For details, see [Introduction to the Hi3516D V300 Development Board](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-lite-introduction-hi3516.md).
2. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
3. Check the serial port number in **QUICK ACCESS** > **DevEco Home** > **Device** in DevEco Device Tool.
![en-us_image_0000001216516128](figures/en-us_image_0000001216516128.png)
> ![icon-note.gif](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/documentation/guide/hi3516_hi3518-drivers-0000001050743695).
4. Choose **QUICK ACCESS** > **DevEco Home** > **Projects**, and then click **Settings**.
![en-us_image_0000001198566364](figures/en-us_image_0000001198566364.png)
5. On the **hi3516dv300** tab page, set the burning options.
- **upload_partitions**: Select the file to be burnt. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are burnt at the same time.
- **upload_port**: Select the serial port number obtained.
- **upload_protocol**: Select the burning protocol **hiburn-usb**.
![en-us_image_0000001223190441](figures/en-us_image_0000001223190441.png)
6. Check the preset information of the files to be burnt and modify them when necessary. The files to be burnt include **fastboot**, **kernel**, **rootfs**, and **userfs**.
1. On the **hi3516dv300_fastboot** tab, select the items to be modified in **New Option**, such as **partition_bin**, **partition_addr**, and **partition_length**.
![en-us_image_0000001198889702](figures/en-us_image_0000001198889702.png)
2. In **Partition Options**, modify the items selected in the preceding step.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Set the start address and length of the partition based on the size of the files to be burnt. Make sure the size of the partition is greater than that of the files to be burnt and the partition addresses of the files to be burnt do not overlap.
![en-us_image_0000001243290907](figures/en-us_image_0000001243290907.png)
3. Follow the same procedure to modify the information about the **kernel**, **rootfs**, and **userfs** files.
7. When you finish modifying, click **Save** on the top.
8. Go to **hi3516dv300** > **Upload** to start burning.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If this is the first time you burn source code to 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 Port Driver on the Hi3516D V300 or Hi3518E V300 Development Board](https://device.harmonyos.com/en/docs/documentation/guide/usb_driver-0000001058690393) and start burning again.
![en-us_image_0000001267231481](figures/en-us_image_0000001267231481.png)
9. When the following information is displayed in the Terminal window, press and hold the reset button, remove and insert the USB cable, and release the reset button to start burning.
![en-us_image_0000001114129426](figures/en-us_image_0000001114129426.png)
If the following message is displayed, it indicates that the burning is successful.
![en-us_image_0000001160649343](figures/en-us_image_0000001160649343.png)
10. When the burning is successful, perform the operations in Running an Image to start the system.
# Running a Hello OHOS Program<a name="EN-US_TOPIC_0000001174270695"></a> # Running
This section describes how to create, compile, burn, and run the first program, and finally print **Hello OHOS!** on the develop board.
## Creating a Program<a name="section204672145202"></a>
1. Create a directory and the program source code.
Create the **applications/sample/camera/apps/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **OHOS** to **World**. You can use either C or C++ to develop a program.
```
#include <stdio.h>
int main(int argc, char **argv)
{
printf("\n************************************************\n");
printf("\n\t\tHello OHOS!\n");
printf("\n************************************************\n\n");
return 0;
}
```
2. Create a build file.
Create the **applications/sample/camera/apps/BUILD.gn** file. The file content is as follows:
```
import("//build/lite/config/component/lite_component.gni")
lite_component("hello-OHOS") {
features = [ ":helloworld" ]
}
executable("helloworld") {
output_name = "helloworld"
sources = [ "src/helloworld.c" ]
include_dirs = []
defines = []
cflags_c = []
ldflags = []
}
```
3. Add a new component.
Add the configuration of the **hello\_world\_app** component to the **build/lite/components/applications.json** file. The sample code below shows some configurations defined in the **applications.json** file, and the code between **\#\#start\#\#** and **\#\#end\#\#** is the new configuration \(Delete the rows where **\#\#start\#\#** and **\#\#end\#\#** are located after the configurations are added.\)
```
{
"components": [
{
"component": "camera_sample_communication",
"description": "Communication related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/communication"
],
"targets": [
"//applications/sample/camera/communication:sample"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##start##
{
"component": "hello_world_app",
"description": "Communication related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/apps"
],
"targets": [
"//applications/sample/camera/apps:hello-OHOS"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##end##
{
"component": "camera_sample_app",
"description": "Camera related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/launcher",
"applications/sample/camera/cameraApp",
"applications/sample/camera/setting",
"applications/sample/camera/gallery",
"applications/sample/camera/media"
],
```
4. Modify the board configuration file.
Add the **hello\_world\_app** component to the **vendor/hisilicon/hispark\_taurus/config.json** file. The sample code below shows the configurations of the **applications** subsystem, and the code between **\#\#start\#\#** and **\#\#end\#\#** is the new configuration \(Delete the rows where **\#\#start\#\#** and **\#\#end\#\#** are located after the configurations are added.\)
```
{
"subsystem": "applications",
"components": [
{ "component": "camera_sample_app", "features":[] },
{ "component": "camera_sample_ai", "features":[] },
##start##
{ "component": "hello_world_app", "features":[] },
##end##
{ "component": "camera_screensaver_app", "features":[] }
]
},
```
## Building<a name="section1077671315253"></a>
If the Linux environment is installed using Docker, perform the building by referring to [Using Docker to Prepare the Build Environment](../get-code/gettools-acquire.md#section107932281315). If the Linux environment is installed using a software package, go to the root directory of the source code and run the following commands for source code compilation:
```
hb set (Set the building path.)
. (Select the current path.)
Select ipcamera_hispark_taurus@hisilicon and press Enter.
hb build -f (Start building.)
```
**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.
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>The U-Boot file of the Hi3516D V300 development board can be obtained from the following path: device/hisilicon/hispark\_taurus/sdk\_liteos/uboot/out/boot/u-boot-hi3516dv300.bin
## Burning<a name="section1347011412201"></a>
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.
### Burning Through the Network Port<a name="section1935410617363"></a>
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.
>![](../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).
![](figures/hi3516-record-the-serial-port-number.png)
3. Open DevEco Device Tool, choose **QUICK ACCESS** \> **DevEco Home** \> **Projects**, and then click **Settings**.
![](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. ## Starting the System
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). After burning is completed, you need to configure the bootloader to run the OpenHarmony system.
- **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.
![](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 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.
![](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 ![](figures/hi3516-deveco-device-tool-logo.png) \> **PROJECT TASKS** \> **hi3516dv300** \> **Upload** to start burning.
![](figures/hi3516-upload-start-burning.png)
10. When the following message is displayed, power off the development board and then power it on.
![](figures/hi3516-restart-the-development-board.png)
11. If the following message is displayed, it indicates that the burning is successful. 1. In the Hi3516D V300 task, click **Configure bootloader (Boot OS)** to configure the bootloader.
![](figures/hi3516-burning-succeeded-net.png) > ![icon-note.gif](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.
12. When the burning is successful, perform the operations in Running an Image to start the system. ![en-us_image_0000001209906547](figures/en-us_image_0000001209906547.png)
### Running an Image<a name="section24721014162010"></a> 2. When the message shown below is displayed, restart the development board. If "SUCCESS" is displayed, it indicates that the configuration is successful.
After burning is completed, you need to configure the bootloader to run the OpenHarmony system. ![en-us_image_0000001210385161](figures/en-us_image_0000001210385161.png)
1. In the Hi3516D V300 task, click **Configure bootloader \(Boot OS\)** to configure the bootloader. 3. Click **Monitor** on the taskbar to start the serial port tool.
>![](../public_sys-resources/icon-note.gif) **NOTE:** ![en-us_image_0000001164506870](figures/en-us_image_0000001164506870.png)
>The bootloader configuration in DevEco Device Tool has been adapted to Hi3516D V300. Therefore, no manual modification is needed.
![](figures/bootloader.png) 4. When the command output is displayed, press **Enter** until **OHOS #** is displayed, indicating that the system is started successfully.
2. When the message shown below is displayed, restart the development board. If **SUCCESS** is displayed, it indicates that the configuration is successful. ![en-us_image_0000001198626874](figures/en-us_image_0000001198626874.png)
![](figures/reset_success.png)
3. Click **Monitor** on the taskbar to start the serial port tool. ## Running a Hello World Program
![](figures/monitor.png) After the system is started, copy the executable file **helloworld** in the **out** directory of the source code to the **bin** directory, and run the Hello World program as follows:
4. Follow the onscreen instructions until **OHOS \#** is displayed, indicating that the system is started successfully. 1. Go to the **bin** directory on the startup page.
```
cd bin
```
![](figures/reboot_success.png) 2. Run the following command to run the **helloworld** program:
```
./helloworld
```
If the message "Hello World!" is displayed, the program runs successfully.
## Running a Program<a name="section5276734182615"></a> ![en-us_image_0000001271234769](figures/en-us_image_0000001271234769.png)
In the root directory, run the **./bin/helloworld** command to operate the demo program. The compilation result is shown in the following example.
**Figure 2** Successful system startup and program execution<a name="fig149821431194515"></a> ## Next
![](figures/successful-system-startup-and-program-execution.png "successful-system-startup-and-program-execution")
Congratulations! You have finished all steps! Proceed to [develop a sample camera with a screen](https://gitee.com/openharmony/docs/blob/master/en/device-dev/guide/device-camera.md) to better familiarize yourself with OpenHarmony development.
# Setting Up the Environment<a name="EN-US_TOPIC_0000001174270689"></a> # Setting Up the Hi3516 Development Board Environment
## Environment Requirements<a name="section179175261196"></a>
### Hardware<a name="section5840424125014"></a> ## Environment Requirements
- Hi3516D V300 IoT camera development board
- USB-to-serial cable and network cable \(The Windows workstation is connected to the Hi3516D V300 development board through the USB-to-serial cable and network cable.\)
The following figure shows the hardware connections. ### Hardware
**Figure 1** Hi3516 hardware connections<a name="fig86246141414"></a> - Hi3516D V300 IoT camera development board
![](figures/hi3516-hardware-connections.png "hi3516-hardware-connections")
### Software<a name="section965634210501"></a> - USB-to-serial cable and network cable (The Linux workstation is connected to the Hi3516D V300 development board through the USB-to-serial cable and network cable.)
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>This section describes how to use an installation package to set up the compilation and development environment. If you are going to use Docker to set up the environment, skip this section and [Installing Linux Build Tools](#section182916865219).
The following table describes the tools required for setting up the general environment for a Linux server of the Hi3516 development board and how to obtain these tools. ### Software
**Table 1** Development tools and obtaining methods The following table describes the tools required for setting up the general environment for a Linux server of the Hi3516D V300 development board.
<a name="table6299192712513"></a> **Table 1** Linux server development tools and functions
<table><thead align="left"><tr id="row122993276512"><th class="cellrowborder" valign="top" width="13.081308130813083%" id="mcps1.2.4.1.1"><p id="p1829914271858"><a name="p1829914271858"></a><a name="p1829914271858"></a>Development Tool</p>
</th>
<th class="cellrowborder" valign="top" width="19.921992199219922%" id="mcps1.2.4.1.2"><p id="p429918274517"><a name="p429918274517"></a><a name="p429918274517"></a>Description</p>
</th>
<th class="cellrowborder" valign="top" width="66.996699669967%" id="mcps1.2.4.1.3"><p id="p12997271757"><a name="p12997271757"></a><a name="p12997271757"></a>How to Obtain</p>
</th>
</tr>
</thead>
<tbody><tr id="row167343191518"><td class="cellrowborder" valign="top" width="13.081308130813083%" headers="mcps1.2.4.1.1 "><p id="p467443191517"><a name="p467443191517"></a><a name="p467443191517"></a>bash</p>
</td>
<td class="cellrowborder" valign="top" width="19.921992199219922%" headers="mcps1.2.4.1.2 "><p id="p0674153114151"><a name="p0674153114151"></a><a name="p0674153114151"></a>Processes CLI commands.</p>
</td>
<td class="cellrowborder" valign="top" width="66.996699669967%" headers="mcps1.2.4.1.3 "><p id="p116746312151"><a name="p116746312151"></a><a name="p116746312151"></a>System configuration</p>
</td>
</tr>
<tr id="row14885193315201"><td class="cellrowborder" valign="top" width="13.081308130813083%" headers="mcps1.2.4.1.1 "><p id="p137174662119"><a name="p137174662119"></a><a name="p137174662119"></a>Basic software package for compilation and building (required only for Ubuntu 20+)</p>
</td>
<td class="cellrowborder" valign="top" width="19.921992199219922%" headers="mcps1.2.4.1.2 "><p id="p258814561424"><a name="p258814561424"></a><a name="p258814561424"></a>Provides a basic software package for compilation and building.</p>
</td>
<td class="cellrowborder" valign="top" width="66.996699669967%" headers="mcps1.2.4.1.3 "><p id="p1749611716181"><a name="p1749611716181"></a><a name="p1749611716181"></a>Internet</p>
</td>
</tr>
<tr id="row52253812238"><td class="cellrowborder" valign="top" width="13.081308130813083%" headers="mcps1.2.4.1.1 "><p id="p28007392236"><a name="p28007392236"></a><a name="p28007392236"></a>dosfstools, mtools, and mtd-utils</p>
</td>
<td class="cellrowborder" valign="top" width="19.921992199219922%" headers="mcps1.2.4.1.2 "><p id="p98008390232"><a name="p98008390232"></a><a name="p98008390232"></a>Pack files.</p>
</td>
<td class="cellrowborder" valign="top" width="66.996699669967%" headers="mcps1.2.4.1.3 "><p id="p280018394233"><a name="p280018394233"></a><a name="p280018394233"></a>apt-get install</p>
</td>
</tr>
<tr id="row29204072315"><td class="cellrowborder" valign="top" width="13.081308130813083%" headers="mcps1.2.4.1.1 "><p id="p5921190162318"><a name="p5921190162318"></a><a name="p5921190162318"></a>Java virtual machine (JVM)</p>
</td>
<td class="cellrowborder" valign="top" width="19.921992199219922%" headers="mcps1.2.4.1.2 "><p id="p17921110152311"><a name="p17921110152311"></a><a name="p17921110152311"></a>Compiles, debugs, and runs Java programs.</p>
</td>
<td class="cellrowborder" valign="top" width="66.996699669967%" headers="mcps1.2.4.1.3 "><p id="p16921805237"><a name="p16921805237"></a><a name="p16921805237"></a>apt-get install</p>
</td>
</tr>
</tbody>
</table>
## Installing Linux Build Tools<a name="section182916865219"></a> | Development Tool| Description|
| -------- | -------- |
| dosfstools, mtools, and mtd-utils| Pack files.|
| Java virtual machine (JVM)| Compiles, debugs, and runs Java programs.|
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>- If you acquire the source code using an HPM component or HPM CLI tool, you do not need to install **hc-gen**.
>- \(Recommended\) If you obtain the source code via the mirror site or code repository, install **hc-gen**. When installing the compilation tool, ensure that its environment variable path is unique.
### Changing Linux Shell to Bash<a name="section1715027152617"></a> ## Installing Linux Build Tools
Check whether bash is used as the shell.
```
ls -l /bin/sh
```
If **/bin/sh -\> bash** is not displayed, do as follows to change shell to bash.
**Method 1:** Run the following command on the device and then click **No**.
```
sudo dpkg-reconfigure dash
```
**Method 2:** Run the first command to delete **sh** and then run the second command to create a new soft link.
```
sudo rm -rf /bin/sh
sudo ln -s /bin/bash /bin/sh
```
### Installing Basic Software Used for Compilation and Building \(Required Only for Ubuntu 20+\)<a name="section45512412251"></a>
Install the software.
```
sudo apt-get install build-essential gcc g++ make zlib* libffi-dev
```
### Installing File Packing Tools and JVM<a name="section16199102083717"></a>
1. Start a Linux server.
2. Install the dosfstools, mtools, mtd-utils, Java Runtime Environment \(JRE\), and Java SDK.
```
sudo apt-get install dosfstools mtools mtd-utils default-jre default-jdk
```
Hi3516D V300 depends on the following tools: dosfstools, mtools, mtd-utils, Java Runtime Environment (JRE), and Java SDK.
These tools have been installed in [Installing Necessary Libraries and Tools](../quick-start/quickstart-lite-env-setup.md#installing-necessary-libraries-and-tools).
# Hi3516<a name="EN-US_TOPIC_0000001128470852"></a> # Hi3516 Development Board
- **[Setting Up the Environment](quickstart-lite-steps-hi3516-setting.md)**
- **[Running a Hello OHOS Program](quickstart-lite-steps-hi3516-running.md)**
- **[Developing a Driver](quickstart-lite-steps-hi3516-program.md)** - **[Setting Up the Hi3516 Development Board Environment](quickstart-lite-steps-hi3516-setting.md)**
- **[FAQs](quickstart-lite-steps-hi3516-faqs.md)** - **[Writing a Hello World Program](quickstart-lite-steps-hi3516-application-framework.md)**
- **[Building](quickstart-lite-steps-hi3516-building.md)**
- **[Burning](quickstart-lite-steps-hi3516-burn.md)**
- **[Running](quickstart-lite-steps-hi3516-running.md)**
# Running
## Viewing Execution Result
After the sample code is compiled, burnt, run, and debugged, restart the development board. If the following messages are displayed, the image is running correctly:
```
ready to OS start
FileSystem mount ok.
wifi init success!
[DEMO] Hello world.
```
## Next
Congratulations! You have finished all steps! Proceed to [develop a sample WLAN product](https://gitee.com/openharmony/docs/blob/master/en/device-dev/guide/device-wlan.md) to better familiarize yourself with OpenHarmony development.
# Writing a Hello World Program
The following exemplifies how to create a program by modifying the source code. The created program outputs the message "Hello world." Perform the steps below in the source code directory.
1. Determine the directory structure.
Before compiling a service, you must create a directory (or a directory structure) in **./applications/sample/wifi-iot/app** to store source code files.
For example, add the **my_first_app** service to the **app** directory, where **hello_world.c** is the service code and **BUILD.gn** is the compilation script. The directory structure is shown as follows:
```
.
└── applications
└── sample
└── wifi-iot
└── app
└── my_first_app
│── hello_world.c
└── BUILD.gn
```
2. Write the service code.
Create the **hello_world.c** file in **./applications/sample/wifi-iot/app/my_first_app**. Then, create the service entry function **HelloWorld** in **hello_world.c** and implement service logic. Call **SYS_RUN()** of OpenHarmony to start the service. (**SYS_RUN** is defined in the **ohos_init.h** file.)
```
#include <stdio.h>
#include "ohos_init.h"
#include "ohos_types.h"
void HelloWorld(void)
{
printf("[DEMO] Hello world.\n");
}
SYS_RUN(HelloWorld);
```
3. Compile the **BUILD.gn** file for building services into a static library.
Create the **BUILD.gn** file in **./applications/sample/wifi-iot/app/my_first_app** and configure the file as follows:
The **BUILD.gn** file consists of three parts, including target, source file, and header file path. You need to fill in all of these parts.
```
static_library("myapp") {
sources = [
"hello_world.c"
]
include_dirs = [
"//utils/native/lite/include"
]
}
```
- Specify the compilation result named **libmyapp.a** in **static_library**. You can fill in this part based on your need.
- Specify the .c file on which a file depends and its path in **sources**. The path that contains **//** represents an absolute path (the code root path). The path that does not contain **//** is a relative path.
- Specify the path of .h file on which **sources** depends in **include_dirs**.
4. Add a component.
Modify the **build/lite/components/applications.json** file and add the configuration of **hello_world_app**. The following code snippet is a snippet of the **applications.json** file: The configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"components": [
{
"component": "camera_sample_communication",
"description": "Communication related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/communication"
],
"targets": [
"//applications/sample/camera/communication:sample"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_a" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##start##
{
"component": "hello_world_app",
"description": "hello world samples.",
"optional": "true",
"dirs": [
"applications/sample/wifi-iot/app/my_first_app"
],
"targets": [
"//applications/sample/wifi-iot/app/my_first_app:myapp"
],
"rom": "",
"ram": "",
"output": [],
"adapted_kernel": [ "liteos_m" ],
"features": [],
"deps": {
"components": [],
"third_party": []
}
},
##end##
{
"component": "camera_sample_app",
"description": "Camera related samples.",
"optional": "true",
"dirs": [
"applications/sample/camera/launcher",
"applications/sample/camera/cameraApp",
"applications/sample/camera/setting",
"applications/sample/camera/gallery",
"applications/sample/camera/media"
],
```
5. Modify the board configuration file.
Modify the **vendor/hisilicon/hispark_pegasus/config.json** file and add an entry of the **hello_world_app** component. The following code snippet is the configuration of the **applications** subsystem, the configuration between \#\#start\#\# and \#\#end\#\# is new. (\#\#start\#\# and \#\#end\#\# are only used to identify the location. After the configuration is complete, delete these lines.)
```
{
"subsystem": "applications",
"components": [
##start##
{ "component": "hello_world_app", "features":[] },
##end##
{ "component": "wifi_iot_sample_app", "features":[] }
]
},
```
# Building
You can build source code with hb or the **build.sh** script. This section exemplifies how to build source code with hb. For details about how to build with the **build.sh** script, see [Building Source Code Using the build.sh Script](../quick-start/quickstart-lite-reference.md).
Go to the root directory of the source code in the Ubuntu environment and perform the following steps:
1. Set the build path.
```
hb set
```
2. Select the current path.
```
.
```
3. Select **wifiiot_hispark_pegasus** under **hisilicon** and press **Enter**.
4. Start building.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - To build a component (for example, **hello**), run the **hb build -T _ Target name _** command.
>
> - To build a product incrementally, run the **hb build** command.
>
> - To build a product from the scratch, run the **hb build -f** command.
>
> This example builds a product from the scratch.
```
hb build -f
```
**Figure 1** Hi3861 build settings
![en-us_image_0000001226634716](figures/en-us_image_0000001226634716.png)
5. Check the build result. If "build success" is displayed, the building is successful.
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> The build result and log files are stored in **out/hispark_pegasus/wifiiot_hispark_pegasus**.
# Burning
Burn the source code to Hi3861 through the serial port in Windows.
### Importing Source Code
After the building is complete, ensure that you can [remotely access the Ubuntu environment from Windows](../quick-start/quickstart-lite-env-setup.md). Then, perform the following steps to import the source code before burning:
1. Open DevEco Device Tool, go to the home page, and click **Import Project** to open your project or source code.
![en-us_image_0000001171426014](figures/en-us_image_0000001171426014.png)
2. Select the target directory (in the Ubuntu environment) and click **Import**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Make sure the selected directory does not contain Chinese characters or spaces. Otherwise, the building may fail.
![en-us_image_0000001227549226](figures/en-us_image_0000001227549226.png)
3. If you select to open the OpenHarmony source code, a message will be displayed indicating that the project is not a DevEco Device Tool project. Click **Import** to continue.
![en-us_image_0000001135394334](figures/en-us_image_0000001135394334.png)
4. On the **Select Project type** page, select **Import from OpenHarmony Source**.
![en-us_image_0000001215743910](figures/en-us_image_0000001215743910.png)
5. On the **Import Project** page, select a product, and the MCU, board, company, and kernel fields will be automatically populated. Then, select the OpenHarmony source code version for **ohosVersion**. Select **wifiiot_hispark_pegasus**.
![en-us_image_0000001272109325](figures/en-us_image_0000001272109325.png)
6. Click **Open** to open the project or source code.
### Burning
After the source code is imported, perform the following steps:
1. Connect the computer and the target development board through the serial port and USB port. For details, see [Introduction to the Hi3861 V100 Development Board](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-lite-introduction-hi3861.md).
2. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
3. Check the serial port number in **QUICK ACCESS** > **DevEco Home** > **Device** in DevEco Device Tool.
![en-us_image_0000001216274840](figures/en-us_image_0000001216274840.png)
> ![icon-note.gif](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 Hi3861 V100](https://device.harmonyos.com/en/docs/documentation/guide/hi3861-drivers-0000001058153433).
4. Choose **QUICK ACCESS** > **DevEco Home** > **Projects**, and then click **Settings**.
![en-us_image_0000001198943768](figures/en-us_image_0000001198943768.png)
5. On the **hi3861** tab page, set the burning options.
- **upload_port**: Select the serial port number obtained.
- **upload_protocol**: Select the burning protocol **hiburn-serial**.
- **upload_partitions**: Select the files to be burnt. **hi3861_app** is selected by default.
![en-us_image_0000001243704061](figures/en-us_image_0000001243704061.png)
6. Check the preset information of the files to be burnt and modify them when necessary.
On the **hi3861_app** tab page, select **partition_bin** from **New Option**, and set the path of the file to be burnt.
![en-us_image_0000001260919759](figures/en-us_image_0000001260919759.png)
7. When you finish modifying, click **Save** on the top.
8. Click **Open** to open the project file. Then, choose **PROJECT TASKS** > **hi3861** > **Upload** to start burning.
![en-us_image_0000001216440138](figures/en-us_image_0000001216440138.png)
9. When the following information is displayed, press the RST button on the development board to restart it.
![en-us_image_0000001198466090](figures/en-us_image_0000001198466090.png)
10. Wait until the burning is complete. When the following message is displayed, the burning is successful.
![en-us_image_0000001216761476](figures/en-us_image_0000001216761476.png)
# Debugging and Verification
When the burning and networking are complete, you can use either of the following methods to debug and verify whether the source code has been burnt correctly:
1. Using printf to print logs
2. Using ASM files to locate panic issues
As the example used here is simple, we use the printf method. The following describes the two methods in detail.
## printf
Add the printf function to the code, which helps print data to the serial port. You can add log printing in key service paths or service exception locations, as shown in the following figure.
```
void HelloWorld(void)
{
printf("[DEMO] Hello world.\n");
}
```
## Using ASM Files to Locate Issues
When the system exits abnormally, the call stack information about the abnormal exit is displayed on the serial port. Analyze the displayed information to troubleshoot and pinpoint issues.
```
=======KERNEL PANIC=======
**Call Stack*
Call Stack 0 -- 4860d8 addr:f784c
Call Stack 1 -- 47b2b2 addr:f788c
Call Stack 2 -- 3e562c addr:f789c
Call Stack 3 -- 4101de addr:f78ac
Call Stack 4 -- 3e5f32 addr:f78cc
Call Stack 5 -- 3f78c0 addr:f78ec
Call Stack 6 -- 3f5e24 addr:f78fc
Call Stack end***
```
To analyze the call stack information, the **Hi3861_wifiiot_app.asm** file is required. This file records the symbol addresses of the functions in the code in the flash memory and the disassembly information. The ASM file is built and output together with the version software package and is stored in the **./out/wifiiot/** directory.
1. (Optional) Save the call stack information to a TXT file for editing.
2. Open the asm file, search for the addresses in CallStack, and list the corresponding function names. Generally, you only need to find the functions matching the first several stacks to locate issues.
```
Call Stack 0 -- 4860d8 addr:f784c -- WadRecvCB
Call Stack 1 -- 47b2b2 addr:f788c -- wal_sdp_process_rx_data
Call Stack 2 -- 3e562c addr:f789c
Call Stack 3 -- 4101de addr:f78ac
Call Stack 4 -- 3e5f32 addr:f78cc
Call Stack 5 -- 3f78c0 addr:f78ec
Call Stack 6 -- 3f5e24 addr:f78fc
```
3. Based on the call stack information, we can conclude that an exception occurs in the **WadRecvCB** function.
![en-us_image_0000001271354733](figures/en-us_image_0000001271354733.png)
4. Check and modify the code.
# Networking
After completing compilation and burning, perform the following to connect the Hi3861 WLAN module to the Internet using AT commands.
1. Click the icon of **DevEco: Serial Monitor** at the bottom of DevEco Device Tool to keep the connection between the Windows workstation and the WLAN module.
**Figure 1** Opening the DevEco Device Tool serial port
![en-us_image_0000001227114644](figures/en-us_image_0000001227114644.png)
2. Reset the Hi3861 WLAN module. The message **ready to OS start** is displayed on the **TERMINAL** panel, indicating that the WLAN module is started successfully.
**Figure 2** Successful resetting of the Hi3861 WLAN module
![en-us_image_0000001226794704](figures/en-us_image_0000001226794704.png)
3. Run the following AT commands in sequence via the serial terminal to start the STA mode, connect to the specified AP, and enable Dynamic Host Configuration Protocol (DHCP).
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> After the development board is started, the serial port prints the test case information. Run the AT command after the test case information is printed. Otherwise, the AT command will be overwritten by the test case information.
```
AT+STARTSTA # Start the STA mode.
AT+SCAN # Scan for available APs.
AT+SCANRESULT # Display the scanning result.
AT+CONN="SSID",,2,"PASSWORD" # Connect to the specified AP. (SSID and PASSWORD represent the name and password of the hotspot to be connected, respectively.)
AT+STASTAT # View the connection result.
AT+DHCP=wlan0,1 # Request the IP address of wlan0 from the AP using DHCP.
```
4. Check whether the Hi3861 WLAN module is properly connected to the gateway, as shown in the following figure.
```
AT+IFCFG # View the IP address assigned to an interface of the module.
AT+PING=X.X.X.X # Check the connectivity between the module and the gateway. Replace X.X.X.X with the actual gateway address.
```
**Figure 3** Successful networking of the Hi3861 WLAN module
![en-us_image_0000001226954648](figures/en-us_image_0000001226954648.png)
# Setting Up the Environment<a name="EN-US_TOPIC_0000001174270691"></a> # Setting Up the Hi3861 Development Board Environment
## Environment Requirements<a name="section466851916410"></a>
### Hardware<a name="section19202111020215"></a>
- Linux compile server
- Windows workstation \(host computer\)
- Hi3861 WLAN module
- USB Type-C cable used to connect the Windows workstation to Hi3861 WLAN module
The following figure shows the hardware connections.
**Figure 1** Hi3861 hardware connections<a name="fig285519359396"></a>
![](figures/hi3861-hardware-connections.png "hi3861-hardware-connections")
### Software<a name="section727451210318"></a>
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>The following part describes how to install tools using installation packages. If you use Docker to set up the build environment, you only need to install the Windows workstation described in [Table 1](#table6299192712513).
The following table lists the tools required for the Hi3861 development board.
**Table 1** Required tools
<a name="table6299192712513"></a>
<table><thead align="left"><tr id="row122993276512"><th class="cellrowborder" valign="top" width="17.54%" id="mcps1.2.5.1.1"><p id="p162491657102110"><a name="p162491657102110"></a><a name="p162491657102110"></a>Platform</p>
</th>
<th class="cellrowborder" valign="top" width="23.59%" id="mcps1.2.5.1.2"><p id="p1829914271858"><a name="p1829914271858"></a><a name="p1829914271858"></a>Development Tool</p>
</th>
<th class="cellrowborder" valign="top" width="22.58%" id="mcps1.2.5.1.3"><p id="p429918274517"><a name="p429918274517"></a><a name="p429918274517"></a>Description</p>
</th>
<th class="cellrowborder" valign="top" width="36.29%" id="mcps1.2.5.1.4"><p id="p12997271757"><a name="p12997271757"></a><a name="p12997271757"></a>How to Obtain</p>
</th>
</tr>
</thead>
<tbody><tr id="row935218593572"><td class="cellrowborder" valign="top" width="17.54%" headers="mcps1.2.5.1.1 "><p id="p105554418586"><a name="p105554418586"></a><a name="p105554418586"></a>Linux server</p>
</td>
<td class="cellrowborder" valign="top" width="23.59%" headers="mcps1.2.5.1.2 "><p id="p45551740589"><a name="p45551740589"></a><a name="p45551740589"></a>Basic software package for compilation and building (required only for Ubuntu 20+)</p>
</td>
<td class="cellrowborder" valign="top" width="22.58%" headers="mcps1.2.5.1.3 "><p id="p655594115814"><a name="p655594115814"></a><a name="p655594115814"></a>Provides a basic software package for compilation and building.</p>
</td>
<td class="cellrowborder" valign="top" width="36.29%" headers="mcps1.2.5.1.4 "><p id="p165558415589"><a name="p165558415589"></a><a name="p165558415589"></a>Internet</p>
</td>
</tr>
<tr id="row1397335913612"><td class="cellrowborder" valign="top" width="17.54%" headers="mcps1.2.5.1.1 "><p id="p3711468218"><a name="p3711468218"></a><a name="p3711468218"></a>Linux server</p>
</td>
<td class="cellrowborder" valign="top" width="23.59%" headers="mcps1.2.5.1.2 "><p id="p097355911620"><a name="p097355911620"></a><a name="p097355911620"></a>SCons 3.0.4+</p>
</td>
<td class="cellrowborder" valign="top" width="22.58%" headers="mcps1.2.5.1.3 "><p id="p1973195917619"><a name="p1973195917619"></a><a name="p1973195917619"></a>Executes script compilation.</p>
</td>
<td class="cellrowborder" valign="top" width="36.29%" headers="mcps1.2.5.1.4 "><p id="p1722663441514"><a name="p1722663441514"></a><a name="p1722663441514"></a>Internet</p>
</td>
</tr>
<tr id="row1968013216717"><td class="cellrowborder" valign="top" width="17.54%" headers="mcps1.2.5.1.1 "><p id="p2681632977"><a name="p2681632977"></a><a name="p2681632977"></a>Linux server</p>
</td>
<td class="cellrowborder" valign="top" width="23.59%" headers="mcps1.2.5.1.2 "><p id="p1991501391312"><a name="p1991501391312"></a><a name="p1991501391312"></a>Python modules: setuptools, Kconfiglib, PyCryptodome, six, and ecdsa</p>
</td>
<td class="cellrowborder" valign="top" width="22.58%" headers="mcps1.2.5.1.3 "><p id="p968120325715"><a name="p968120325715"></a><a name="p968120325715"></a>Executes script compilation.</p>
</td>
<td class="cellrowborder" valign="top" width="36.29%" headers="mcps1.2.5.1.4 "><p id="p268116326711"><a name="p268116326711"></a><a name="p268116326711"></a>Internet</p>
</td>
</tr>
<tr id="row020914491313"><td class="cellrowborder" valign="top" width="17.54%" headers="mcps1.2.5.1.1 "><p id="p20209749103116"><a name="p20209749103116"></a><a name="p20209749103116"></a>Linux server</p>
</td>
<td class="cellrowborder" valign="top" width="23.59%" headers="mcps1.2.5.1.2 "><p id="p7209104910317"><a name="p7209104910317"></a><a name="p7209104910317"></a>gcc riscv32</p>
</td>
<td class="cellrowborder" valign="top" width="22.58%" headers="mcps1.2.5.1.3 "><p id="p102093498311"><a name="p102093498311"></a><a name="p102093498311"></a>Executes script compilation.</p>
</td>
<td class="cellrowborder" valign="top" width="36.29%" headers="mcps1.2.5.1.4 "><p id="p321054953116"><a name="p321054953116"></a><a name="p321054953116"></a>Internet</p>
</td>
</tr>
<tr id="row1596703610215"><td class="cellrowborder" valign="top" width="17.54%" headers="mcps1.2.5.1.1 "><p id="p071946112113"><a name="p071946112113"></a><a name="p071946112113"></a>Windows workstation</p>
</td>
<td class="cellrowborder" valign="top" width="23.59%" headers="mcps1.2.5.1.2 "><p id="p1044974291416"><a name="p1044974291416"></a><a name="p1044974291416"></a>CH341SER.EXE</p>
</td>
<td class="cellrowborder" valign="top" width="22.58%" headers="mcps1.2.5.1.3 "><p id="p94491342131413"><a name="p94491342131413"></a><a name="p94491342131413"></a>USB-to-Serial adapter driver</p>
</td>
<td class="cellrowborder" valign="top" width="36.29%" headers="mcps1.2.5.1.4 "><p id="p6449184214148"><a name="p6449184214148"></a><a name="p6449184214148"></a><a href="http://www.wch-ic.com/search?t=downloads&amp;q=ch340g" target="_blank" rel="noopener noreferrer">http://www.wch-ic.com/search?t=downloads&amp;q=ch340g</a></p>
</td>
</tr>
</tbody>
</table>
## Installing Linux Build Tools<a name="section497484245614"></a>
>![](../public_sys-resources/icon-notice.gif) **NOTICE:**
>- If you acquire the source code using an HPM component or HPM CLI tool, you do not need to install **gcc\_riscv32**.
>- \(Recommended\) If you obtain the source code via the mirror site or code repository, install **gcc\_riscv32**. When installing the compilation tool, ensure that its environment variable path is unique.
### Installing Basic Software Used for Compilation and Building \(Required Only for Ubuntu 20+\)<a name="section45512412251"></a>
Install the software.
```
sudo apt-get install build-essential gcc g++ make zlib* libffi-dev
```
### Installing Scons<a name="section7438245172514"></a>
1. Start a Linux server.
2. Install the SCons installation package.
```
python3 -m pip install scons
```
3. Check whether the installation is successful. ## Environment Requirements
```
scons -v
```
**Figure 2** Successful installation \(SCons version requirement: 3.0.4 or later\)<a name="fig151441613316"></a> ### Hardware
![](figures/successful-installation-(scons-version-requirement-3-0-4-or-later).png "successful-installation-(scons-version-requirement-3-0-4-or-later)")
- Linux workstation
### Installing Python Modules<a name="section88701892341"></a> - Hi3861 WLAN module
1. Install setuptools. - USB Type-C cable used to connect the Linux workstation to Hi3861 development board
```
pip3 install setuptools
```
2. Install the GUI menuconfig tool \(Kconfiglib\). You are advised to install Kconfiglib 13.2.0 or later. ### Software
- **Command line:**
```
sudo pip3 install kconfiglib
```
- **Installation package:** The following table lists the tools required by the Hi3861 WLAN module.
1. Download the **.whl** file \(for example, **kconfiglib-13.2.0-py2.py3-none-any.whl**\).
Download path: [https://pypi.org/project/kconfiglib\#files](https://pypi.org/project/kconfiglib#files)
1. Install the **.whl** file. **Table 1 Tools required by the Hi3861 WLAN module
``` | Development Tool| Description|
sudo pip3 install kconfiglib-13.2.0-py2.py3-none-any.whl | -------- | -------- |
``` | SCons3.0.4+ | Executes script compilation.|
| Python modules: setuptools, Kconfiglib, PyCryptodome, six, and ecdsa| Executes script compilation.|
| gcc&nbsp;riscv32 | Executes script compilation.|
3. Install **PyCryptodome** using either of the following methods: ## Installing the Compilation Tools
Install the Python component packages on which the file signature depends, including PyCryptodome, six, and ecdsa. As the installation of **ecdsa** depends on that of **six**, install **six** first. Perform the following steps to install the necessary tools:
- **Command line:**
``` ### Installing Scons
sudo pip3 install pycryptodome
```
- **Installation package:** 1. Run the following command to install the SCons installation package:
1. Download the **.whl** file \(for example, **pycryptodome-3.9.9-cp38-cp38-manylinux1\_x86\_64.whl**\).
```
python3 -m pip install scons
```
Download path: [https://pypi.org/project/pycryptodome/\#files](https://pypi.org/project/pycryptodome/#files) 2. Run the following command to check whether SCons is successfully installed. If the installation is successful, the query result as shown in Figure 1 is displayed.
```
scons -v
```
1. Install the **.whl** file. **Figure 1** Successful SCons installation (the version must be 3.0.4 or later)
``` ![en-us_image_0000001271234749](figures/en-us_image_0000001271234749.png)
sudo pip3 install pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl
```
4. Install **six** using either of the following methods: ### Installing Python Modules
- **Command line:**
``` 1. Install setuptools.
sudo pip3 install six --upgrade --ignore-installed six
``` ```
pip3 install setuptools
```
- **Installation package:** 2. Install the GUI menuconfig tool (Kconfiglib). You are advised to install Kconfiglib 13.2.0 or later.
1. Download the **.whl** file, for example, **six-1.12.0-py2.py3-none-any.whl**.
Download path: [https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files) - Command line:
```
sudo pip3 install kconfiglib
```
1. Install the **.whl** file. - Installation package:
``` 1. Download the .whl file, for example, **kconfiglib-13.2.0-py2.py3-none-any.whl**.
sudo pip3 install six-1.12.0-py2.py3-none-any.whl
```
Download path: [https://pypi.org/project/kconfiglib#files](https://pypi.org/project/kconfiglib#files)
5. Install **ecdsa** using either of the following methods: 2. Install the .whl file.
- **Command line:**
```
sudo pip3 install kconfiglib-13.2.0-py2.py3-none-any.whl
```
``` 3. Install PyCryptodome using either of the following methods:
sudo pip3 install ecdsa
```
- **Installation package:** Install the Python component packages on which the file signature depends, including **PyCryptodome**, **six**, and **ecdsa**. As the installation of **ecdsa** depends on that of **six**, install **six** first.
1. Download the **.whl** file, for example, **ecdsa-0.14.1-py2.py3-none-any.whl**.
Download path: [https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files) - Command line:
```
sudo pip3 install pycryptodome
```
- Installation package:
1. Install the **.whl** file. 1. Download the .whl file , for example, **pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl**.
``` Download path: [https://pypi.org/project/pycryptodome/#files](https://pypi.org/project/pycryptodome/#files)
sudo pip3 install ecdsa-0.14.1-py2.py3-none-any.whl
```
2. Install the .whl file.
```
sudo pip3 install pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl
```
4. Install **six** using either of the following methods:
- Command line:
```
sudo pip3 install six --upgrade --ignore-installed six
```
### Installing gcc\_riscv32 \(Compiler Toolchain for WLAN Module\)<a name="section34435451256"></a> - Installation package:
>![](../public_sys-resources/icon-notice.gif) **NOTICE:** 1. Download the .whl file, for example, **six-1.12.0-py2.py3-none-any.whl**.
>- 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 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. Download path: [https://pypi.org/project/six/#files](https://pypi.org/project/six/#files)
2. Install the **GCC**, **G++**, **Bison**, **Flex**, **Makeinfo** tools to ensure that the toolchain can be correctly compiled.
``` 2. Install the .whl file.
sudo apt-get install gcc g++ flex bison texinfo
``` ```
sudo pip3 install six-1.12.0-py2.py3-none-any.whl
```
3. Download the RISC-V GNU toolchain. 5. Install **ecdsa** using either of the following methods:
``` - Command line:
git clone --recursive https://gitee.com/mirrors/riscv-gnu-toolchain.git
``` ```
sudo pip3 install ecdsa
```
4. Open the **riscv-gnu-toolchain** folder and delete empty folders to prevent conflicts during the download of **Newlib**, **Binutils**, and **GCC**. - Installation package:
``` 1. Download the .whl file, for example, **ecdsa-0.14.1-py2.py3-none-any.whl**.
cd riscv-gnu-toolchain && rm -rf riscv-newlib && rm -rf riscv-binutils && rm -rf riscv-gcc
```
5. Download RISC-V Newlib 3.0.0. Download path: [https://pypi.org/project/ecdsa/#files](https://pypi.org/project/ecdsa/#files)
``` 2. Install the .whl file.
git clone -b riscv-newlib-3.0.0 https://github.com/riscv/riscv-newlib.git
``` ```
sudo pip3 install ecdsa-0.14.1-py2.py3-none-any.whl
```
6. Download RISC-V Binutils 2.31.1.
``` ### Installing gcc_riscv32 (Compilation Toolchain for the WLAN Module)
git clone -b riscv-binutils-2.31.1 https://github.com/riscv/riscv-binutils-gdb.git
```
7. Download RISC-V GCC 7.3.0. > ![icon-notice.gif](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 14 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.
``` 1. Start a Linux server.
git clone -b riscv-gcc-7.3.0 https://github.com/riscv/riscv-gcc
```
8. Add the RISC-V GCC 7.3.0 patch. 2. Download the **RISC-V GNU** toolchain.
```
git clone --recursive https://gitee.com/mirrors/riscv-gnu-toolchain.git
```
Visit the GCC official patch links [89411](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=026216a753ef0a757a9e368a59fa667ea422cf09;hp=2a23a1c39fb33df0277abd4486a3da64ae5e62c2) and [86724](https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/graphite.h;h=be0a22b38942850d88feb159603bb846a8607539;hp=4e0e58c60ab83f1b8acf576e83330466775fac17;hb=b1761565882ed6a171136c2c89e597bc4dd5b6bf;hpb=fbd5f023a03f9f60c6ae36133703af5a711842a3), and manually add the changes to the .c and .h files based on the requirements in the patch links. Note that the number of rows may not match because of different versions of the patch and GCC. You need to search for the keyword in the patch to locate the corresponding row. 3. Open the **riscv-gnu-toolchain** folder and delete empty folders to prevent conflicts during the download of **Newlib**, **Binutils**, and **GCC**.
```
cd riscv-gnu-toolchain && rm -rf riscv-newlib && rm -rf riscv-binutils && rm -rf riscv-gcc
```
9. Download, decompress, and install [GMP 6.1.2](https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2). 4. Download RISC-V Newlib 3.0.0.
```
git clone -b riscv-newlib-3.0.0 https://github.com/riscv/riscv-newlib.git
```
``` 5. Download RISC-V Binutils 2.31.1.
tar -xvf gmp-6.1.2.tar.bz2 && mkdir build_gmp && cd build_gmp && ../gmp-6.1.2/configure --prefix=/usr/local/gmp-6.1.2 --disable-shared --enable-cxx && make && make install
``` ```
git clone -b riscv-binutils-2.31.1 https://github.com/riscv/riscv-binutils-gdb.git
```
10. Download, decompress, and install [mpfr-4.0.2](https://www.mpfr.org/mpfr-4.0.2/mpfr-4.0.2.tar.gz). 6. Download RISC-V GCC 7.3.0.
```
git clone -b riscv-gcc-7.3.0 https://github.com/riscv/riscv-gcc
```
``` 7. Add the RISC-V GCC 7.3.0 patch.
tar -xvf mpfr-4.0.2.tar.gz && mkdir build_mpfr && cd build_mpfr && ../mpfr-4.0.2/configure --prefix=/usr/local/mpfr-4.0.2 --with-gmp=/usr/local/gmp-6.1.2 --disable-shared && make && make install
``` Visit the GCC official patch links [89411](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=026216a753ef0a757a9e368a59fa667ea422cf09;hp=2a23a1c39fb33df0277abd4486a3da64ae5e62c2) and [86724](https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/graphite.h;h=be0a22b38942850d88feb159603bb846a8607539;hp=4e0e58c60ab83f1b8acf576e83330466775fac17;hb=b1761565882ed6a171136c2c89e597bc4dd5b6bf;hpb=fbd5f023a03f9f60c6ae36133703af5a711842a3), and manually add the changes to the .c and .h files based on the requirements in the patch links. Note that the number of rows may not match because of different versions of the patch and GCC. You need to search for the keyword in the patch to locate the corresponding row.
8. Download, decompress, and install [GMP 6.1.2](https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2).
```
tar -xvf gmp-6.1.2.tar.bz2 && mkdir build_gmp && cd build_gmp && ../gmp-6.1.2/configure --prefix=/usr/local/gmp-6.1.2 --disable-shared --enable-cxx && make && make install
```
11. Download, decompress, and install [mpc-1.1.0](https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz). 9. Download, decompress, and install [mpfr-4.0.2 ](https://www.mpfr.org/mpfr-4.0.2/mpfr-4.0.2.tar.gz).
```
tar -xvf mpfr-4.0.2.tar.gz && mkdir build_mpfr && cd build_mpfr && ../mpfr-4.0.2/configure --prefix=/usr/local/mpfr-4.0.2 --with-gmp=/usr/local/gmp-6.1.2 --disable-shared && make && make install
```
10. Download, decompress, and install [mpc-1.1.0](https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz).
``` ```
tar -xvf mpc-1.1.0.tar.gz && mkdir build_mpc && cd build_mpc && ../mpc-1.1.0/configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 --disable-shared && make && make install tar -xvf mpc-1.1.0.tar.gz && mkdir build_mpc && cd build_mpc && ../mpc-1.1.0/configure --prefix=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 --disable-shared && make && make install
``` ```
12. Open the **riscv-gnu-toolchain** folder and create a directory for toolchain output. 11. Open the **riscv-gnu-toolchain** folder and create a directory for toolchain output.
``` ```
cd /opt && mkdir gcc_riscv32 cd /opt && mkdir gcc_riscv32
``` ```
13. Compile **binutils**. 12. Compile binutils.
``` ```
mkdir build_binutils && cd build_binutils && ../riscv-binutils-gdb/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32/riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. mkdir build_binutils && cd build_binutils && ../riscv-binutils-gdb/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32/riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd ..
``` ```
14. Build **Newlib**. 13. Build Newlib.
``` ```
mkdir build_newlib && cd build_newlib && ../riscv-newlib/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" \CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd .. mkdir build_newlib && cd build_newlib && ../riscv-newlib/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" \CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --bindir=/opt/gcc_riscv32/bin --libexecdir=/opt/gcc_riscv32 --libdir=/opt/gcc_riscv32 --includedir=/opt/gcc_riscv32 && make -j16 && make install && cd ..
``` ```
15. Build **GCC**. 14. Build GCC.
``` ```
mkdir build_gcc && cd build_gcc && ../riscv-gcc/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" LDFLAGS="-Wl,-z,relro,-z,now,-z,noexecstack" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --with-headers="/opt/gcc-riscv32/riscv32-unknown-elf/include" --with-mpc=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 && make -j16 && make install mkdir build_gcc && cd build_gcc && ../riscv-gcc/configure --prefix=/opt/gcc_riscv32 --target=riscv32-unknown-elf --with-arch=rv32imc --with-abi=ilp32 --disable-__cxa_atexit --disable-libgomp --disable-libmudflap --enable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-multilib --enable-poison-system-directories --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --with-newlib --with-system-zlib CFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" CXXFLAGS="-fstack-protector-strong -O2 -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack -fPIE" LDFLAGS="-Wl,-z,relro,-z,now,-z,noexecstack" CXXFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" CFLAGS_FOR_TARGET="-Os -mcmodel=medlow -Wall -fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -Wtrampolines -fno-short-enums -fno-short-wchar" --with-headers="/opt/gcc-riscv32/riscv32-unknown-elf/include" --with-mpc=/usr/local/mpc-1.1.0 --with-gmp=/usr/local/gmp-6.1.2 --with-mpfr=/usr/local/mpfr-4.0.2 && make -j16 && make install
``` ```
16. Set an environment variable. 15. Set the environment variable.
>![](../public_sys-resources/icon-note.gif) **NOTE:** > ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
>If you use the compiled **riscv32 gcc** package, perform the following steps to set environment variables: > If you are using the riscv32 gcc package, run the following command to decompress the package to the root directory:
>1. Decompress the package to the root directory. >
> ``` > ```
> tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~
> ``` > ```
>2. Set an environment variable.
> ```
> vim ~/.bashrc
> ```
>3. Copy the following command to the last line of the **.bashrc** file, save the file, and exit.
> ```
> export PATH=~/gcc_riscv32/bin:$PATH
> ```
``` ```
vim ~/.bashrc vim ~/.bashrc
``` ```
Copy the following command to the last line of the **.bashrc** file, save the file, and exit. Copy the following command to the last line of the .bashrc file, save the file, and exit.
``` ```
export PATH=~/gcc_riscv32/bin:$PATH export PATH=~/gcc_riscv32/bin:$PATH
``` ```
17. Validate the environment variable. 16. Validate the environment variable.
``` ```
source ~/.bashrc source ~/.bashrc
``` ```
18. Check whether the compiler is successfully installed. If the compiler version number is correctly displayed, the installation is successful. 17. Check whether the compiler is successfully installed. If the compiler version number is correctly displayed, the installation is successful.
``` ```
riscv32-unknown-elf-gcc -v riscv32-unknown-elf-gcc -v
``` ```
## Installing the USB-to-Serial Driver<a name="section1027732411513"></a>
Perform the following operations on the Windows station.
1. Download the USB-to-serial driver: [CH341SER USB-to-serial driver](http://www.hihope.org/en/download/download.aspx).
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.
![](figures/serial-port-entry.png)
# Hi3861<a name="EN-US_TOPIC_0000001174350609"></a> # Hi3861 Development Board
- **[Setting Up the Environment](quickstart-lite-steps-hi3861-setting.md)**
- **[Setting Up WLAN Connection](quickstart-lite-steps-hi3861-connection.md)**
- **[Running a Hello World Program](quickstart-lite-steps-hi3861-running.md)** - **[Setting Up the Hi3861 Development Board Environment](quickstart-lite-steps-hi3861-setting.md)**
- **[FAQs](quickstart-lite-steps-hi3861-faqs.md)** - **[Writing a Hello World Program](quickstart-lite-steps-hi3861-application-framework.md)**
- **[Building](quickstart-lite-steps-hi3861-building.md)**
- **[Burning](quickstart-lite-steps-hi3861-burn.md)**
- **[Networking](quickstart-lite-steps-hi3861-netconfig.md)**
- **[Debugging and Verification](quickstart-lite-steps-hi3861-debug.md)**
- **[Running](quickstart-lite-steps-hi3816-running.md)**
# How to Develop<a name="EN-US_TOPIC_0000001128470860"></a> # Running a Hello World Program
- **[Hi3861](quickstart-lite-steps-hi3861.md)**
- **[Hi3516](quickstart-lite-steps-hi3516.md)**
- **[Hi3518](quickstart-lite-steps-hi3518.md)**
- **[Hi3861 Development Board](quickstart-lite-steps-hi3861.md)**
- **[Hi3516 Development Board](quickstart-lite-steps-hi3516.md)**
# Mini and Small Systems<a name="EN-US_TOPIC_0000001112826850"></a> # Getting Started with Mini and Small Systems
- **[Overview](quickstart-lite-overview.md)**
- **[Introduction](quickstart-lite-introduction.md)**
- **[Environment Setup](quickstart-lite-env-setup.md)**
- **[How to Develop](quickstart-lite-steps.md)**
- **[Getting Started with Mini and Small Systems (IDE Mode)](quickstart-lite-ide-directory.md)**
- **[Getting Started with Mini and Small Systems (Installation Package Mode)](quickstart-lite-package-directory.md)**
# Appendix
- **[Introduction to Development Boards](quickstart-standard-board-introduction.md)**
- **[Reference](quickstart-standard-reference.md)**
# Introduction to the Hi3516 Development Board
## Overview
Hi3516D V300 is a next-generation system on chip (SoC) designed for industry-dedicated smart HD IP cameras. 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** Hi3516 front view
![en-us_image_0000001226922318](figures/en-us_image_0000001226922318.png)
## Development Board Specifications
**Table 1** Hi3516 specifications
| Item| Description|
| -------- | -------- |
| Processor and internal memory| -&nbsp;Hi3516D V300 chip<br>-&nbsp;DDR3&nbsp;1 GB<br>-&nbsp;eMMC 4.5, 8 GB capacity|
| External components| -&nbsp;Ethernet port<br>-&nbsp;Audio and video<br>&nbsp;&nbsp;-&nbsp;1 voice input<br>&nbsp;&nbsp;-&nbsp;1 mono channel (AC_L) output, connected to a 3 W power amplifier (LM4871)<br>&nbsp;&nbsp;-&nbsp;MicroHDMI (1-channel HDMI 1.4)<br>-&nbsp;Camera<br>&nbsp;&nbsp;-&nbsp;Sensor IMX335<br>&nbsp;&nbsp;-&nbsp;M12 lens, 4 mm focal length, and 1.8 aperture<br>-&nbsp;Display<br>&nbsp;&nbsp;-&nbsp;LCD connector (2.35-inch)<br>&nbsp;&nbsp;-&nbsp;LCD connector (5.5-inch)<br>-&nbsp;External components and ports<br>&nbsp;&nbsp;-&nbsp;Memory card port<br>&nbsp;&nbsp;-&nbsp;JTAG/I2S port<br>&nbsp;&nbsp;-&nbsp;ADC port<br>&nbsp;&nbsp;-&nbsp;Steering gear port<br>&nbsp;&nbsp;-&nbsp;Grove connector<br>&nbsp;&nbsp;-&nbsp;USB 2.0 (Type-C)<br>&nbsp;&nbsp;-&nbsp;Three function keys, two user-defined keys, and one upgrade key<br>&nbsp;&nbsp;-&nbsp;LED indicator, green or red|
# Introduction to the RK3568 Development Board
## Overview
Bolstered by the Rockchip RK3568 chip, the RK3568 development board integrates a dual-core GPU and high-efficiency NPU. Its quad-core 64-bit Cortex-A55 processor uses the advanced 22 nm manufacturing process and is clocked at up to 2.0 GHz. The development board is packed with Bluetooth, Wi-Fi, audio, video, and camera features, with a wide range of expansion ports as well as video input and output ports. It comes with dual GE auto-sensing RJ45 ports, so it can be used in multi-connectivity products, such as NVRs and industrial gateways.
**Figure 1** Front view of the RK3568 development board
![en-us_image_0000001271442261](figures/en-us_image_0000001271442261.png)
**Figure 2** RK3568 rear view
![en-us_image_0000001226602394](figures/en-us_image_0000001226602394.png)
## Development Board Specifications
**Table 1** RK3568 specifications
| Item| Description|
| -------- | -------- |
| Display| -&nbsp;1 x HDMI 2.0 (Type-A) port, supporting 4K/60 fps output<br>-&nbsp;2 x MIPI, supporting 1920 x 1080\@60 fps output<br>-&nbsp; 1 x eDP, supporting 2K@60 fps output|
| Audio port| -&nbsp;1 x 8ch I2S/TDM/PDM<br>-&nbsp;1 x HDMI<br>-&nbsp;1 x speaker output<br>-&nbsp;1 x headset output<br>-&nbsp;1 x microphone for onboard audio input|
| Ethernet port| 2 x GMAC (10/100/1000M)|
| Wireless connectivity| SDIO port, supporting Wi-Fi 6 5G/2.5 GHz and Bluetooth 4.2|
| Camera port| MIPI-CSI2, 1 x 4-lane/2x2-lane\@2.5 Gbps/lane|
| USB port| -&nbsp;2 x USB 2.0 Host, Type-A<br>-&nbsp;1 x USB 3.0 Host, Type-A<br>-&nbsp;1 x USB3.0 OTG|
| PCIe | 1 x 2-lane PCIe 3.0 Connector (RC mode)|
| SATA | 1×SATA3.0&nbsp;Connector |
| SDMMC port| 1 x microSD card 3.0 |
| Keys| -&nbsp;1 x Vol+/Recovery<br>-&nbsp;1 x Reset<br>-&nbsp;1 x Power<br>-&nbsp;1 x Vol-<br>-&nbsp;1 x Mute|
| Debugging port| 1 x Debugging serial port|
| RTC | 1 x RTC|
| IR | 1 x IR|
| Tri-color indicator| 3 x LED|
| G-sensor | 1 x G-sensor|
| Fan| 1 x Fan|
| Expansion port| The 20-pin expansion ports include:<br>-&nbsp;2 x ADC<br>-&nbsp; 2 x I2C<br>-&nbsp;7 x GPIO (or 3 x GPIO + 4 x UART)<br>-&nbsp;3 x VCC power (12 V, 3.3 V, and 5 V)|
| Mother board dimensions| 180 mm x 130 mm|
| PCB| 4-laminate|
# Introduction to Development Boards
- **[Introduction to the Hi3516 Development Board](quickstart-standard-board-introduction-hi3516.md)**
- **[Introduction to the RK3568 Development Board](quickstart-standard-board-introduction-rk3568.md)**
# Getting Started with Standard System (Using the Installation Package)
- **[Standard System Overview](quickstart-standard-overview.md)**
- **[Setting Up Environments for Standard System](quickstart-standard-env-setup.md)**
- **[Running a Hello World Project](quickstart-standard-running.md)**
- **[FAQs](quickstart-standard-faqs.md)**
- **[Appendix](quickstart-standard-appendix.md)**
# Setting Up Environments for Standard System
## System Requirements
- Windows: Windows 10 (64-bit)
- Ubuntu: Ubuntu 18.04 or later; recommended memory: 16 GB or higher.
- User name: cannot contain Chinese characters
- DevEco Device Tool: 3.0 Release
## Installing Necessary Libraries and Tools
To install the necessary libraries and tools, perform the following steps.
In Ubuntu:
1. Run the following **apt-get** command:
```
sudo apt-get update && sudo apt-get install binutils binutils-dev git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib gcc-arm-linux-gnueabi libc6-dev-i386 libc6-dev-amd64 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 bc gnutls-bin python3.8 python3-pip ruby genext2fs device-tree-compiler make libffi-dev e2fsprogs pkg-config perl openssl libssl-dev libelf-dev libdwarf-dev u-boot-tools mtd-utils cpio doxygen liblz4-tool openjdk-8-jre gcc g++ texinfo dosfstools mtools default-jre default-jdk libncurses5 apt-utils wget scons python3.8-distutils tar rsync git-core libxml2-dev lib32z-dev grsync xxd libglib2.0-dev libpixman-1-dev kmod jfsutils reiserfsprogs xfsprogs squashfs-tools pcmciautils quota ppp libtinfo-dev libtinfo5 libncurses5-dev libncursesw5 libstdc++6 gcc-arm-none-eabi vim ssh locales
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The preceding command is applicable to Ubuntu 18.04. For other Ubuntu versions, modify the preceding installation command based on the installation package name. Specifically:
>
> - Python 3.8 or a later version is required. This section uses Python 3.8 as an example.
>
> - Java 8 or later is required. This section uses Java 8 as an example.
2. Set Python 3.8 as the default Python version.
Check the location of Python 3.8:
```
which python3.8
```
Change python and python3 to python3.8.
```
sudo update-alternatives --install /usr/bin/python python {python3.8 path} 1 #{Python3.8 path} is the location of Python 3.8 obtained in the previous step.
sudo update-alternatives --install /usr/bin/python3 python3 {python3.8 path} 1 #{Python3.8 path} is the location of Python 3.8 obtained in the previous step.
```
## Installing DevEco Device Tool
To remotely access the Ubuntu environment through Windows to perform operations such as burning, you need to install DevEco Device Tool on both Windows and Ubuntu.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> DevEco Device Tool is a one-stop integrated development environment (IDE) provided for developers of OpenHarmony-powered smart devices. It allows code editing, compiling, burning, and debugging. This document describes how to use DevEco Device Tool to remotely connect to the Ubuntu environment for burning and running.
### Installing DevEco Device Tool for Windows
1. Download the [DevEco Device Tool 3.0 Release](https://device.harmonyos.com/cn/ide#download) Windows edition.
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**. You are advised to install DevEco Device Tool in a non-system drive.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If you have installed DevEco Device Tool 3.0 Beta2 or earlier, the earlier version will be uninstalled before you install a new version. If the following error message is displayed during the uninstallation, click **Ignore** to continue the installation. This error does not affect the installation of the new version.
>
> ![en-us_image_0000001239275843](figures/en-us_image_0000001239275843.png)
![en-us_image_0000001270076961](figures/en-us_image_0000001270076961.png)
4. When prompted, select the tools to be automatically installed.
1. On the **VSCode installation confirm** page, select **Install VScode 1.62.2 automatically** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Visual Studio Code 1.62 or later has been installed, this step will be skipped.
![en-us_image_0000001237801283](figures/en-us_image_0000001237801283.png)
2. On the displayed **Python select page**, select **Download from Huawei mirror** and click **Next**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If Python 3.8 or 3.9 has been installed, select **Use one of compatible on your PC**.
![en-us_image_0000001193983334](figures/en-us_image_0000001193983334.png)
5. In the dialog box shown below, click **Next** to download and install the tools..
![en-us_image_0000001239634067](figures/en-us_image_0000001239634067.png)
6. Wait for the DevEco Device Tool setup wizard to automatically install DevEco Device Tool. After the installation is complete, click **Finish** to close the setup wizard.
![en-us_image_0000001239650137](figures/en-us_image_0000001239650137.png)
7. From Visual Studio Code, access the DevEco Device Tool page. Now you can conduct your development in DevEco Device Tool.
![en-us_image_0000001225760456](figures/en-us_image_0000001225760456.png)
### Installing DevEco Device Tool for Ubuntu
1. Make sure the Ubuntu shell environment is **bash**.
1. Run the following command and check whether the command output is **bash**. If the command output is not **bash**, go to step 2.
```
ls -l /bin/sh
```
![en-us_image_0000001226764302](figures/en-us_image_0000001226764302.png)
2. Start the command-line tool, run the following command, enter your password, and select **No** to set **Ubuntu shell** to **bash**.
```
sudo dpkg-reconfigure dash
```
![en-us_image_0000001243641075](figures/en-us_image_0000001243641075.png)
2. Download the [DevEco Device Tool 3.0 Release Linux version](https://device.harmonyos.com/cn/ide#download).
3. Decompress the DevEco Device Tool software package and assign permission on the folder obtained from the decompression.
1. Go to the directory where the DevEco Device Tool software package is stored and run the following command to decompress the software package. In the command, change **devicetool-linux-tool-3.0.0.400.zip** to the actual software package name.
```
unzip devicetool-linux-tool-3.0.0.400.zip
```
2. Open the folder of the decompressed software package and run the following command to grant the execute permission on the installation file. In the command, change **devicetool-linux-tool-3.0.0.400.sh** to the actual installation file name.
```
chmod u+x devicetool-linux-tool-3.0.0.400.sh
```
4. Run the following command to install DevEco Device Tool, where **devicetool-linux-tool-3.0.0.400.sh** indicates the installation file name.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> During the installation, the setup wizard automatically checks whether Python 3.8 or 3.9 is installed. If Python 3.8 or 3.9 is not installed, the setup wizard displays the "Do you want to continue?" message; enter **Y** to allow the setup wizard to automatically install Python.
```
sudo ./devicetool-linux-tool-3.0.0.400.sh
```
Wait until the "Deveco Device Tool successfully installed." message is displayed.
![en-us_image_0000001198722374](figures/en-us_image_0000001198722374.png)
## Configuring Windows to Remotely Access the Ubuntu Build Environment
### Installing the SSH Service and Obtaining the IP Address for Remote Access
1. In Ubuntu, open the Terminal tool and run the following command to install the SSH service:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the command fails to be executed and the system displays a message indicating that the openssh-server and openssh-client depend on different versions, install the openssh-client of the required version (for example, **sudo apt-get install openssh-client=1:8.2p1-4**) as prompted on the command-line interface (CLI) and run the command again to install the openssh-server.
```
sudo apt-get install openssh-server
```
2. Run the following command to start the SSH service:
```
sudo systemctl start ssh
```
3. Run the following command to obtain the IP address of the current user for remote access to the Ubuntu environment from Windows:
```
ifconfig
```
![en-us_image_0000001215737140](figures/en-us_image_0000001215737140.png)
### Installing Remote SSH
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001239080359](figures/en-us-cn_image_0000001239080359.png), and search for **remote-ssh** in the Extension Marketplace.
![en-us_image_0000001193920448](figures/en-us_image_0000001193920448.png)
2. Click **Install** to install Remote-SSH. After the installation is successful, **Remote-SSH** is displayed on the **INSTALLED** list.
![en-us_image_0000001238880335](figures/en-us_image_0000001238880335.png)
### Remotely Connecting to the Ubuntu Environment
1. Open Visual Studio Code in Windows, click ![en-us_image_0000001238760373](figures/en-us_image_0000001238760373.png), and click + on the **REMOTE EXOPLORER** page.
![en-us_image_0000001215878922](figures/en-us_image_0000001215878922.png)
2. In the **Enter SSH Connection Command** text box, enter **ssh *username@ip_address***, where *ip_address* indicates the IP address of the remote computer to be connected and *username* indicates the account name used for logging in to the remote computer.
![en-us_image_0000001215879750](figures/en-us_image_0000001215879750.png)
3. In the displayed dialog box, select the default first option as the SSH configuration file.
![en-us_image_0000001260519729](figures/en-us_image_0000001260519729.png)
4. Under **SSH TARGETS**, find the remote computer and click ![en-us_image_0000001194080414](figures/en-us_image_0000001194080414.png) to start it.
![en-us_image_0000001215720398](figures/en-us_image_0000001215720398.png)
5. In the displayed dialog box, select **Linux**, select **Continue**, and enter the password for logging in to the remote computer.
![en-us_image_0000001215897530](figures/en-us_image_0000001215897530.png)
After the connection is successful, the plug-in is automatically installed in the .vscode-server folder on the remote computer. After the installation is complete, reload Visual Studio Code in Windows as prompted. Then you can develop, compile, and burn source code in DevEco Device Tool on Windows.
### Registering the Public Key for Accessing the Ubuntu Environment
After the preceding operations are complete, you can remotely connect to the Ubuntu environment through Windows for development. However, you need to frequently enter the remote connection password. To eliminate this need, you can use the SSH public key.
1. Open the Git bash CLI and run the following command to generate an SSH public key. During command execution, perform operations as prompted. Set **username** and **ip** to the user name and IP address you use for connecting to the Ubuntu system.
```
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub username@ip
```
![en-us_image_0000001271532317](figures/en-us_image_0000001271532317.png)
2. In Visual Studio Code, click the remote connection setting button and open the **config** file.
![en-us_image_0000001226034634](figures/en-us_image_0000001226034634.png)
3. In the **config** file, add the SSK key file information, as shown below. Then save the file.
![en-us_image_0000001270356233](figures/en-us_image_0000001270356233.png)
## Obtaining Source Code
In the Ubuntu environment, perform the following steps to obtain the OpenHarmony source code:
### Preparations
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
3. Install the git client and git-lfs. (Skip this step if these tools have been installed in Installing Required Libraries and Tools. )
Update the software source:
```
sudo apt-get update
```
Run the following command to install the tools:
```
sudo apt-get install git git-lfs
```
4. Configure user information.
```
git config --global user.name "yourname"
git config --global user.email "your-email-address"
git config --global credential.helper store
```
5. Run the following commands to install the **repo** tool:
```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
```
### Obtaining Source Code
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master 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'
```
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'
```
- **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../../release-notes/Readme.md).
### Running prebuilts
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
```
## Installing the Compilation Tool
hb is a compilation tool of OpenHarmony. To install hb in Ubuntu, perform the following steps: For details about the functions of the OpenHarmony compilation and building module, see [Compilation and Building Guidelines](https://gitee.com/openharmony/docs/blob/master/en/device-dev/subsystems/subsys-build.md).
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> To install a proxy, see [Configuring a Proxy](../quick-start/quickstart-standard-reference.md#configuring-a-proxy).
1. Run the following command to install hb and update it to the latest version:
```
pip3 install --user build/lite
```
2. Set the environment variable.
```
vim ~/.bashrc
```
Copy the following command to the last line of the .bashrc file, save the file, and exit.
```
export PATH=~/.local/bin:$PATH
```
Update the environment variable.
```
source ~/.bashrc
```
3. Run the **hb -h** command in the source code directory. If the following information is displayed, the installation is successful:
```
usage: hb
OHOS build system
positional arguments:
{build,set,env,clean}
build Build source code
set OHOS build settings
env Show OHOS build env
clean Clean output
optional arguments:
-h, --help show this help message and exit
```
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> - Run the following command to uninstall hb:
>
> ```
> pip3 uninstall ohos-build
> ```
>
> - If any issue occurs during the hb installation, see [FAQs](../quick-start/quickstart-standard-faq-hb.md) to troubleshoot.
# Fixing Burning Issues
## What should I do if Error: Opening COMxx: Access denied is displayed when I start burning
- **Symptom**
Error: Opening COMxx: Access denied is displayed after clicking Burn and selecting a serial port.
**Figure 1** Failed to open the serial port
![en-us_image_0000001271202461](figures/en-us_image_0000001271202461.png)
- **Possible Causes**
The serial port is in use.
- **Solution**
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 in use
![en-us_image_0000001271202473](figures/en-us_image_0000001271202473.png)
2. Click the dustbin icon as shown below to disable the terminal using the serial port.
**Figure 3** Disabling the terminal using the serial port
![en-us_image_0000001271202469](figures/en-us_image_0000001271202469.png)
3. Click **Burn**, select the serial port, and start burning images again.
**Figure 4** Restarting the burning task
![en-us_image_0000001271562449](figures/en-us_image_0000001271562449.png)
## What should I do when Windows-based PC failed to be connected to the board?
- **Symptom**
The file image cannot be obtained after clicking Burn and selecting a serial port.
**Figure 5** Failed to obtain the file image due to network disconnection
![en-us_image_0000001226922306](figures/en-us_image_0000001226922306.png)
- **Possible Causes**
The board is disconnected from the Windows-based PC.
Windows Firewall does not allow Visual Studio Code to access the network.
- **Solution**
1. Check whether the network cable is properly connected.
2. Click **Windows Firewall**.
**Figure 6** Network and firewall settings
![en-us_image_0000001226634732](figures/en-us_image_0000001226634732.png)
3. Click **Firewall & network protection**, and on the displayed page, click **Allow an app through the firewall**.
**Figure 7** Firewall & network protection
![en-us_image_0000001271202457](figures/en-us_image_0000001271202457.png)
4. Select Visual Studio Code.
**Figure 8** Selecting Visual Studio Code
![en-us_image_0000001271234765](figures/en-us_image_0000001271234765.png)
5. Select the **Private** and **Public** network access rights for Visual Studio Code.
**Figure 9** Allowing Visual Studio Code to access the network
![en-us_image_0000001271474585](figures/en-us_image_0000001271474585.png)
## What should I do when the image failed to be burnt?
- **Symptom**
The burning status is not displayed after clicking Burn and selecting a serial port.
- **Possible Causes**
The IDE is not restarted after the DevEco plug-in is installed.
- **Solution**
Restart the IDE.
# Fixing Compilation Issues
## What should I do if the message "ImportError: No module named apt_pkg" is displayed during the execution of an unidentifiable command?
- **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.
- **Solution**
Reinstall python3-apt.
```
sudo apt-get remove python3-apt
sudo apt-get install python3-apt
```
## What should I do if the message indicating Python cannot be found is displayed during compilation and building?
- **Symptom**
The following error occurs during compilation and building:
```
-bash: /usr/bin/python: No such file or directory
```
- **Possible Cause 1**
Python is not installed.
- **Solution**
Run the following command to install Python. The following uses Python 3.8 as an example.
```
sudo apt-get install python3.8
```
- **Possible Cause 2**
The soft link that points to the Python does not exist in the **usr/bin** directory.
![en-us_image_0000001226922322](figures/en-us_image_0000001226922322.png)
- **Solution**
Run the following commands to add a soft link:
```
# cd /usr/bin/
# which python3
# ln -s /usr/local/bin/python3 python
# python --version
```
Example:
![en-us_image_0000001271562453](figures/en-us_image_0000001271562453.png)
## What should I do if the message indicating Python 3 cannot be found is displayed during the build process?
- **Symptom**
![en-us_image_0000001226602414](figures/en-us_image_0000001226602414.png)
- **Possible Causes**
Python 3 is not installed.
- **Solution**
Run the following command to install Python 3:
```
sudo apt-get install python3.8
```
## What should I do if the message "configure: error: no acceptable C compiler found in $PATH" is displayed during Python 3 installation?
- **Symptom**
The following error occurs during Python 3 installation:
```
configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details
```
- **Possible Causes**
**gcc** is not installed.
- **Solution**
1. Run the **apt-get install gcc** command to install **gcc** online.
2. After the installation, reinstall Python 3.
## What should I do if the message "-bash: make: command not found" is displayed during Python 3 installation?
- **Symptom**
The following error occurs during Python 3 installation:
```
-bash: make: command not found
```
- **Possible Causes**
Make is not installed.
- **Solution**
1. Run the **apt-get install make** command to install Make online.
2. After the installation, reinstall Python 3.
## What should I do if the message "No module named '_ctypes'" is displayed during Python 3 installation?
- **Symptom**
The following error occurs during Python 3 installation:
```
ModuleNotFoundError: No module named '_ctypes'
```
- **Possible Causes**
**libffi** and **libffi-devel** are not installed.
- **Solution**
1. Run the **apt-get install libffi* -y** command to install **libffi** and **libffi-devel** online.
2. After the installation, reinstall Python 3.
## What should I do if the message "No module named 'Crypto'" is displayed during the build process?
- **Symptom**
The following error occurs during compilation and building:
```
ModuleNotFoundError: No module named 'Crypto'
```
- **Possible Causes**
**Crypto** is not installed.
- **Solution**
Solution 1: Run the **pip3 install Crypto** command to install **Crypto** online.
Method 2: Offline installation
Download the source code from [PyPI](https://pypi.org/project/pycrypto/#files).
![en-us_image_0000001227082334](figures/en-us_image_0000001227082334.png)
Save the source package to the Linux server, decompress the package, and run the **python3 setup.py install** command to install Crypto.
After the preceding installation is complete, rebuild an environment.
# Fixing hb Installation Issues
## What should I do if garbled characters and segmentation faults occur during hb installation?
- **Symptom**
Garbled characters and segmentation faults occur during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
pip is of an early version.
- **Solution**
Upgrade pip.
```
python3 -m pip install -U pip
```
## What should I do if the message "cannot import 'sysconfig' from 'distutils'" is displayed during hb installation?
- **Symptom**
The message "cannot import 'sysconfig' from 'distutils'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
The **distutils** module is unavailable.
- **Solution**
Install distutils.
```
sudo apt-get install python3.8-distutils
```
## What should I do if the message "module 'platform' has no attribute 'linux_distribution'" is displayed during hb installation?
- **Symptom**
The message "module 'platform' has no attribute 'linux_distribution'" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
There is a compatibility issue of python3-pip.
- **Solution**
Reinstall pip.
```
sudo apt remove python3-pip
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
```
## What should I do if the message "Could not find a version that satisfies the requirement ohos-build" is displayed during hb installation?
- **Symptom**
The message "Could not find a version that satisfies the requirement ohos-build" is displayed during the execution of the **python3 -m pip install --user ohos-build** command.
- **Possible Causes**
The installation fails due to poor network connectivity.
- **Solution**
1. Ensure that your computer has a good network connection. If the network connection is unstable, rectify the network fault and reinstall hb.
2. If the network is functional, run the following commands to install hb by specifying a temporary PyPI source:
```
python3 -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple ohos-build
```
# FAQs<a name="EN-US_TOPIC_0000001166804465"></a> # FAQs
## 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. - **[Fixing hb Installation Issues](quickstart-standard-faq-hb.md)**
- **Possible Causes** - **[Fixing Compilation Issues](quickstart-standard-faq-compose.md)**
There is a compatibility issue of python3-apt.
- **Solution**
Reinstall python3-apt.
```
sudo apt-get remove python3-apt
sudo apt-get install python3-apt
```
- **[Fixing Burning Issues](quickstart-standard-faq-burning.md)**
## Getting Started with Standard System (IDE Mode)
- [Standard System Overview](quickstart-ide-standard-overview.md)
- Environment Preparation
- [Setting Up the Windows+Ubuntu Hybrid Build Environment](quickstart-ide-standard-env-setup-win-ubuntu.md)
- [Obtaining Source Code](quickstart-ide-standard-sourcecode-acquire.md)
- [Creating a Source Code Project](quickstart-ide-standard-create-project.md)
- Running a Hello World Program
- Hi3516 Development Board
- [Writing a Hello World Program](quickstart-ide-standard-running-hi3516-create.md)
- [Building](quickstart-ide-standard-running-hi3516-build.md)
- [Burning](quickstart-ide-standard-running-hi3516-burning.md)
- [Running](quickstart-ide-standard-running-hi3516-running.md)
- RK3568 Development Board
- [Writing a Hello World Program](quickstart-ide-standard-running-rk3568-create.md)
- [Building](quickstart-ide-standard-running-rk3568-build.md)
- [Burning](quickstart-ide-standard-running-rk3568-burning.md)
- [Running](quickstart-ide-standard-running-rk3568-running.md)
- Appendix
- Introduction to Development Boards
- [Introduction to the Hi3516 Development Board](quickstart-ide-standard-board-introduction-hi3516.md)
- [Introduction to the RK3568 Development Board](quickstart-ide-standard-board-introduction-rk3568.md)
- [Getting Started with Mini and Small Systems (Installation Package Mode)](quickstart-lite-package-directory.md)
# Getting Started with Standard System (IDE Mode)
- **[Standard System Overview](quickstart-ide-standard-overview.md)**
- **[Environment Preparation](quickstart-ide-standard-env-setup.md)**
- **[Creating a Source Code Project](quickstart-ide-standard-create-project.md)**
- **[Running a Hello World Program](quickstart-ide-standard-running.md)**
- **[Appendix](quickstart-ide-standard-appendix.md)**
# Introduction<a name="EN-US_TOPIC_0000001166764513"></a> # Standard System Overview
This document helps you quickly understand how to set up a standard OpenHarmony system, and how to build, burn, and start the system. You can develop the standard system in Windows and build source code in Linux.
This document uses the recommended Hi3516D V300 development board as an example. ## Introduction
## Quick Start Process<a name="section7825218111517"></a> The OpenHarmony standard system applies to devices with a reference memory greater than or equal to 128 MiB. This document helps you quickly get started for development of the OpenHarmony standard system, from environment setup to building, burning, and startup.
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. To accommodate different developer habits, OpenHarmony provides two modes for getting started with the standard system:
**Figure 1** Getting started for the standard system<a name="fig19162195553211"></a> - IDE mode: DevEco Device Tool is used for one-stop development, covering dependency installation, building, burning, and running.
![](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> - Installation package mode: Dependency download and installation as well as building operations are performed using commands. Burning and running are performed in DevEco Device Tool.
OpenHarmony also provides the [Docker environment](../get-code/gettools-acquire.md), which can significantly simplify the environment configuration before compilation. You can build your source code in the Docker environment if you are more accustomed to using the installation package mode.
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. This document exemplifies how to use the installation package mode. For details about the IDE mode, see [Getting Started with Standard System (IDE Mode)](../quick-start/quickstart-standard-ide-directory.md).
**Figure 2** Hi3516D V300 front view<a name="fig202901538183412"></a>
![](figures/hi3516d-v300-front-view-1.png "hi3516d-v300-front-view-1")
## Development Board Specifications<a name="en-us_topic_0000001053666242_section15192203316533"></a> ## Development Environment
**Table 1** Specifications of the Hi3516 development board In the Windows+Ubuntu hybrid environment for OpenHarmony development:
<a name="en-us_topic_0000001053666242_table31714894311"></a> - Windows: used for source code development and burning.
<table><thead align="left"><tr id="en-us_topic_0000001053666242_row10171198194310"><th class="cellrowborder" valign="top" width="14.77%" id="mcps1.2.3.1.1"><p id="en-us_topic_0000001053666242_a2b235e9ed55f4338886788f140e648a0"><a name="en-us_topic_0000001053666242_a2b235e9ed55f4338886788f140e648a0"></a><a name="en-us_topic_0000001053666242_a2b235e9ed55f4338886788f140e648a0"></a>Item</p>
</th>
<th class="cellrowborder" valign="top" width="85.22999999999999%" id="mcps1.2.3.1.2"><p id="en-us_topic_0000001053666242_p9702458104014"><a name="en-us_topic_0000001053666242_p9702458104014"></a><a name="en-us_topic_0000001053666242_p9702458104014"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="en-us_topic_0000001053666242_row0171168114311"><td class="cellrowborder" valign="top" width="14.77%" headers="mcps1.2.3.1.1 "><p id="en-us_topic_0000001053666242_p1698185431418"><a name="en-us_topic_0000001053666242_p1698185431418"></a><a name="en-us_topic_0000001053666242_p1698185431418"></a>Processor and internal memory</p>
</td>
<td class="cellrowborder" valign="top" width="85.22999999999999%" headers="mcps1.2.3.1.2 "><a name="en-us_topic_0000001053666242_ul1147113537186"></a><a name="en-us_topic_0000001053666242_ul1147113537186"></a><ul id="en-us_topic_0000001053666242_ul1147113537186"><li>Hi3516D V300</li><li>1 GB DDR3</li><li>8 GB eMMC4.5</li></ul>
</td>
</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 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>
</li></ul>
</td>
</tr>
</tbody>
</table>
- Ubuntu: used for source code building.
This document describes how to develop OpenHarmony in the Windows+Ubuntu environment.
## Development Boards
In this document, two development board models are used as examples: Hi3516D V300 and RK3516. For details about these development boards, see [Appendix](../quick-start/quickstart-standard-board-introduction.md). You can purchase the development board as required.
## Development Process
Below you can see the quick start process for the development of the standard system.
**Figure 1** Quick start process for the development of the standard system
![en-us_image_0000001226634676](figures/en-us_image_0000001226634676.png)
## Getting Started with Standard System (Installation Package Mode)
- [Standard System Overview](quickstart-standard-overview.md)
- [Setting Up Environments for Standard System](quickstart-standard-env-setup.md)
- Running a Hello World Program
- Hi3516 Development Board
- [Writing a Hello World Program](quickstart-standard-running-hi3516-create.md)
- [Building](quickstart-standard-running-hi3516-build.md)
- [Burning](quickstart-standard-running-hi3516-burning.md)
- [Running](quickstart-standard-running-hi3516-running.md)
- RK3568 Development Board
- [Writing a Hello World Program](quickstart-standard-running-rk3568-create.md)
- [Building](quickstart-standard-running-rk3568-build.md)
- [Burning](quickstart-standard-running-rk3568-burning.md)
- [Running](quickstart-standard-running-rk3568-running.md)
- FAQs
- [Fixing hb Installation Issues](quickstart-standard-faq-hb.md)
- [Fixing Compilation Issues](quickstart-standard-faq-compose.md)
- [Fixing Burning Issues](quickstart-standard-faq-burning.md)
- Appendix
- Introduction to Development Boards
- [Introduction to the Hi3516 Development Board](quickstart-standard-board-introduction-hi3516.md)
- [Introduction to the RK3568 Development Board](quickstart-standard-board-introduction-rk3568.md)
- [Getting Started with Standard System (IDE Mode)](quickstart-standard-ide-directory.md)
- [Reference](quickstart-standard-reference.md)
# Reference
## Using the build.sh Script to Build Source Code
1. Go to the root directory of the source code and run the build command.
```
./build.sh --product-name name --ccache
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> _name_ indicates the product name, for example, **Hi3516D V300** and **rk3568**.
2. Check the build result. After the build is complete, the following information is displayed in the log:
```
post_process
=====build name successful.
```
Files generated during the build are stored in the **out/{device_name}/** directory, and the generated image is stored in the **out/{device_name}/packages/phone/images/** directory.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> For details about other modular compilation operations, see [Building a Standard System](../subsystems/subsys-build-standard-large.md).
## Configuring the Proxy
### Setting Up the Python Proxy
1. Create a proxy configuration file.
```
mkdir ~/.pipvim ~/.pip/pip.conf
```
2. Add the following proxy information to the file, save the file, and exit:
```
[global]
index-url = http:// Proxy URL
trusted-host = Trusted image path
timeout = 120
```
### Setting Up the npm Proxy
1. Create a proxy configuration file.
```
vim ~/.npmrc
```
2. Add the following proxy information to the file, save the file, and exit:
```
Registry=http:// Proxy URL
strict-ssl=false
```
3. Add the following content to the **.bashrc** file, save the file, and exit:
```
export NPM_REGISTRY=http:// Proxy URL
source .bashrc
```
# Building
You can build source code with hb or the **build.sh** script. This section exemplifies how to build source code with hb. For details about how to build with the **build.sh** script, see [Building Source Code Using the build.sh Script](../quick-start/quickstart-standard-reference.md).
Go to the root directory of the source code in the Ubuntu environment and perform the following steps:
1. Set the build path.
```
hb set
```
2. Select the current path.
```
.
```
3. Select **Hi3516D V300** under **built-in** and press **Enter**.
4. Start building.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - To build a component (for example, **hello**), run the **hb build -T _ Target name _** command.
>
> - To build a product incrementally, run the **hb build** command.
>
> - To build a product from the scratch, run the **hb build -f** command.
>
> This example builds a product from the scratch.
```
hb build -f
```
**Figure 1** Hi3516 build settings
![en-us_image_0000001271562433](figures/en-us_image_0000001271562433.png)
5. Check the build result. If "build success" is displayed, the building is successful.
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> The build result and log files are stored in **out/hi3516dv300**.
# Burning
To burn source code to Hi3516D V300 through the USB port in Windows, perform the following steps.
### Importing Source Code
After the building is complete, ensure that you can [remotely access the Ubuntu environment from Windows](../quick-start/quickstart-standard-env-setup.md). Then, perform the following steps to import the source code before burning:
1. Open DevEco Device Tool, go to the home page, and click **Import Project** to open your project or source code.
![en-us_image_0000001171426014](figures/en-us_image_0000001171426014.png)
2. Select the target directory (in the Ubuntu environment) and click **Import**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Make sure the selected directory does not contain Chinese characters or spaces. Otherwise, the building may fail.
![en-us_image_0000001227711882](figures/en-us_image_0000001227711882.png)
3. If you select to open the OpenHarmony source code, a message will be displayed indicating that the project is not a DevEco Device Tool project. Click **Import** to continue.
![en-us_image_0000001135394334](figures/en-us_image_0000001135394334.png)
4. On the **Select Project type** page, select **Import from OpenHarmony Source**.
![en-us_image_0000001215743910](figures/en-us_image_0000001215743910.png)
5. On the **Import Project** page, select a product, and the MCU, board, company, and kernel fields will be automatically populated. Then, select the OpenHarmony source code version for **ohosVersion**. In the figure below, **Hi3516DV300** is used as an example.
![en-us_image_0000001271912277](figures/en-us_image_0000001271912277.png)
6. Click **Open** to open the project or source code.
### Burning
After the source code is imported, perform the following steps:
1. Connect the computer and the target development board through the serial port and USB port. For details, see [Introduction to the Hi3516D V300 Development Board](https://gitee.com/openharmony/docs/blob/master/en/device-dev/quick-start/quickstart-lite-introduction-hi3516.md).
2. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. In this case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
3. Check the serial port number in **QUICK ACCESS** > **DevEco Home** > **Device** in DevEco Device Tool.
![en-us_image_0000001216516128](figures/en-us_image_0000001216516128.png)
> ![icon-note.gif](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/documentation/guide/hi3516_hi3518-drivers-0000001050743695).
4. Choose **QUICK ACCESS** > **DevEco Home** > **Projects**, and then click **Settings**.
![en-us_image_0000001198566364](figures/en-us_image_0000001198566364.png)
5. On the **hi3516dv300** tab page, set the burning options.
- **upload_partitions**: Select the file to be burnt. By default, the **fastboot**, **kernel**, **rootfs**, and **userfs** files are burnt at the same time.
- **upload_port**: Select the serial port number obtained.
- **upload_protocol**: Select the burning protocol **hiburn-usb**.
![en-us_image_0000001223190441](figures/en-us_image_0000001223190441.png)
6. Check the preset information of the files to be burnt and modify them when necessary. The files to be burnt include **fastboot**, **kernel**, **rootfs**, and **userfs**.
1. On the **hi3516dv300_fastboot** tab, select the items to be modified in **New Option**, such as **partition_bin**, **partition_addr**, and **partition_length**.
![en-us_image_0000001198889702](figures/en-us_image_0000001198889702.png)
2. In **Partition Options**, modify the items selected in the preceding step.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Set the start address and length of the partition based on the size of the files to be burnt. Make sure the size of the partition is greater than that of the files to be burnt and the partition addresses of the files to be burnt do not overlap.
![en-us_image_0000001243290907](figures/en-us_image_0000001243290907.png)
3. Follow the same procedure to modify the information about the **kernel**, **rootfs**, and **userfs** files.
7. When you finish modifying, click **Save** on the top.
8. Go to **hi3516dv300** > **Upload** to start burning.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If this is the first time you burn source code to 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 Port Driver on the Hi3516D V300 or Hi3518E V300 Development Board](https://device.harmonyos.com/en/docs/documentation/guide/usb_driver-0000001058690393) and start burning again.
![en-us_image_0000001267231481](figures/en-us_image_0000001267231481.png)
9. When the following information is displayed in the Terminal window, press and hold the reset button, remove and insert the USB cable, and release the reset button to start burning.
![en-us_image_0000001114129426](figures/en-us_image_0000001114129426.png)
If the following message is displayed, it indicates that the burning is successful.
![en-us_image_0000001160649343](figures/en-us_image_0000001160649343.png)
10. When the burning is successful, perform the operations in Running an Image to start the system.
# Writing a Hello World Program
The following exemplifies how to run the first program on the development board. The created program outputs the message "Hello World!" .
## Example Directory
The complete code directory is as follows:
```
applications/sample/hello
│ │── BUILD.gn
│ │── include
│ │ └── helloworld.h
│ │── src
│ │ └── helloworld.c
│ └── bundle.json
build
└── subsystem_config.json
productdefine/common
└── products
└── Hi3568DV300.json
```
## How to Develop
Perform the steps below in the source code directory:
1. Create a directory and write the service code.
Create the **applications/sample/hello/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **World** to **OH**. Declare the string printing function **HelloPrint** in the **helloworld.h** file. You can use either C or C++ to develop a program.
```
#include <stdio.h>
#include "helloworld.h"
int main(int argc, char **argv)
{
HelloPrint();
return 0;
}
void HelloPrint()
{
printf("\n\n");
printf("\n\t\tHello World!\n");
printf("\n\n");
}
```
Add the header file **applications/sample/hello/include/helloworld.h**. The sample code is as follows:
```
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
void HelloPrint();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // HELLOWORLD_H
```
2. Create a build file.
1. Create the **applications/sample/hello/BUILD.gn** file. The file content is as follows:
```
import("//build/ohos.gni") # Import the build template.
ohos_executable("helloworld") {# Executable module.
sources = [ # Source code of the module.
"src/helloworld.c"
]
include_dirs = [ # Directory of header file on which the module depends.
"include"
]
cflags = []
cflags_c = []
cflags_cc = []
ldflags = []
configs = []
deps =[] # Internal dependencies of a component.
part_name = "hello" # Component name. This parameter is mandatory.
install_enable = true # Whether to install the software by default. This parameter is optional. By default, the software is not installed.
}
```
2. Create the **applications/sample/hello/bundle.json** file and add the description of the **sample** component. The content is as follows:
```
{
"name": "@ohos/hello",
"description": "Hello world example.",
"version": "3.1",
"license": "Apache License 2.0",
"publishAs": "code-segment",
"segment": {
"destPath": "applications/sample/hello"
},
"dirs": {},
"scripts": {},
"component": {
"name": "hello",
"subsystem": "sample",
"syscap": [],
"features": [],
"adapted_system_type": [ "mini", "small", "standard" ],
"rom": "10KB",
"ram": "10KB",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [
"//applications/sample/hello:helloworld"
],
"inner_kits": [],
"test": []
}
}
}
```
The **bundle.json** file consists of two parts. The first part describes the information about the subsystem to which the component belongs, and the second part defines the component building configuration. When adding a part, you need to specify the **sub_component** contained in the part. If there are interfaces provided for other components, describe them in **inner_kits**. If there are test cases, describe them in **test**.
3. Modify the subsystem configuration file.
Add the configuration of the new subsystem to the **build/subsystem_config.json** file.
```
"sample": {
"path": "applications/sample/hello",
"name": "sample"
},
```
4. Modify the product configuration file.
In the **productdefine/common/products/Hi3516DV300.json** file, add the **hello** part after the existing part.
```
"usb:usb_manager_native":{},
"applications:prebuilt_hap":{},
"sample:hello":{},
"wpa_supplicant-2.9:wpa_supplicant-2.9":{},
```
# Running
## Starting the System
After the burning is complete, perform the following steps to start the system in Windows:
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation procedure is required only if this is the first time you burn an image for the standard system.
1. In DevEco Device Tool, click **Monitor** to open the serial port tool.
![en-us_image_0000001226762374](figures/en-us_image_0000001226762374.png)
2. Restart the development board. Before the autoboot countdown ends, press any key to enter the system.
![en-us_image_0000001271442265](figures/en-us_image_0000001271442265.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 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 0x82000000 0x800 0x4800; bootm 0x82000000'
```
![en-us_image_0000001271322437](figures/en-us_image_0000001271322437.png)
4. Save the parameter settings.
```
save
```
![en-us_image_0000001271562437](figures/en-us_image_0000001271562437.png)
5. Restart the development board to start the system.
```
reset
```
![en-us_image_0000001226762378](figures/en-us_image_0000001226762378.png)
## Running a Hello World Program
After the system is started, start the serial port tool, run the **helloworld** command in any directory, and press **Enter**. If the message "Hello World!" is displayed, the program runs successfully.
![en-us_image_0000001226602398](figures/en-us_image_0000001226602398.png)
## Next
Congratulations! You have finished all steps! Proceed to [develop a sample](../guide/device-clock-guide.md) to better familiarize yourself with OpenHarmony development.
# Hi3516 Development Board
- **[Writing a Hello World Program](quickstart-standard-running-hi3516-create.md)**
- **[Building](quickstart-standard-running-hi3516-build.md)**
- **[Burning](quickstart-standard-running-hi3516-burning.md)**
- **[Running](quickstart-standard-running-hi3516-running.md)**
# Building
You can build source code with hb or the **build.sh** script. This section exemplifies how to build source code with hb. For details about how to build with the **build.sh** script, see [Building Source Code Using the build.sh Script](../quick-start/quickstart-standard-reference.md).
Go to the root directory of the source code in the Ubuntu environment and perform the following steps:
1. Set the build path.
```
hb set
```
2. Select the current path.
```
.
```
3. Select **rk3568** under **built-in** and press **Enter**.
4. Start building.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> - To build a component (for example, **hello**), run the **hb build -T _ Target name _** command.
>
> - To build a product incrementally, run the **hb build** command.
>
> - To build a product from the scratch, run the **hb build -f** command.
>
> This example builds a product from the scratch.
```
hb build -f
```
**Figure 1** RK3568 build settings
![en-us_image_0000001226922302](figures/en-us_image_0000001226922302.png)
5. Check the build result. If "rk3568 build success" is displayed, the building is successful.
> ![icon-notice.gif](public_sys-resources/icon-notice.gif) **NOTICE**
> The build result and log files are stored in **out/rk3568**.
# Burning
To burn source code to RK3568 on Windows, perform the following steps:
### Importing Source Code
After the building is complete, ensure that you can [remotely access the Ubuntu environment from Windows](../quick-start/quickstart-standard-env-setup.md). Then, perform the following steps to import the source code before burning:
1. Open DevEco Device Tool, go to the home page, and click **Import Project** to open your project or source code.
![en-us_image_0000001171426014](figures/en-us_image_0000001171426014.png)
2. Select the target directory (in the Ubuntu environment) and click **Import**.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Make sure the selected directory does not contain Chinese characters or spaces. Otherwise, the building may fail.
![en-us_image_0000001272032361](figures/en-us_image_0000001272032361.png)
3. If you select to open the OpenHarmony source code, a message will be displayed indicating that the project is not a DevEco Device Tool project. Click **Import** to continue.
![en-us_image_0000001135394334](figures/en-us_image_0000001135394334.png)
4. On the **Select Project type** page, select **Import from OpenHarmony Source**.
![en-us_image_0000001215743910](figures/en-us_image_0000001215743910.png)
5. On the **Import Project** page, select a product, and the MCU, board, company, and kernel fields will be automatically populated. Then, select the OpenHarmony source code version for **ohosVersion**. Select **rk3568**.
![en-us_image_0000001227712350](figures/en-us_image_0000001227712350.png)
6. Click **Open** to open the project or source code.
### Burning
After the source code is imported, perform the following steps:
1. [Download](https://gitee.com/hihope_iot/docs/blob/master/HiHope_DAYU200/%E7%83%A7%E5%86%99%E5%B7%A5%E5%85%B7%E5%8F%8A%E6%8C%87%E5%8D%97/windows/DriverAssitant_v5.1.1.zip) **DriverInstall.exe**. Double-click **DriverInstall.exe** to open the installer. Then click the install button to install the USB driver as prompted.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> If the burning tool of an earlier version has been installed, uninstall it first.
2. Connect the computer to the target development board through the USB port.
3. In DevEco Device Tool, choose **REMOTE DEVELOPMENT** > **Local PC** to check the connection status between the remote computer (Ubuntu build environment) and the local computer (Windows build environment).
- If ![en-us_image_0000001261315939](figures/en-us_image_0000001261315939.png) is displayed on the right of **Local PC**, the remote computer is connected to the local computer. Inthis case, no further action is required.
- If ![en-us_image_0000001261515989](figures/en-us_image_0000001261515989.png) is displayed, click the connect icon.
![en-us_image_0000001261395999](figures/en-us_image_0000001261395999.png)
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This operation is required only in remote access mode (in the Windows+Ubuntu hybrid build environment). If the local access mode (Windows or Ubuntu build environment) is used, skip this step.
4. In DevEco Device Tool, choose QUICK ACCESS > DevEco Home > Projects, and then click Settings.
![en-us_image_0000001239661509](figures/en-us_image_0000001239661509.png)
5. On the **hh_scdy200** tab page, set the burning options.
- **upload_partitions**: Select the files to be burnt.
- **upload_protocol**: Select the burning protocol **upgrade**.
![en-us_image_0000001194504874](figures/en-us_image_0000001194504874.png)
6. Check the preset information of the files to be burnt and modify them when necessary. The files to be burnt include **loader**, **parameter**, **uboot**, **boot_linux**, **system**, **vendor**, and **userdata**.
1. On the **hh_scdy200_loader** tab, select the items to be modified in **New Option**, such as **partition_bin**, **partition_addr**, and **partition_length**.
![en-us_image_0000001224173270](figures/en-us_image_0000001224173270.png)
2. In **Partition Options**, modify the items selected in the preceding step.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Set the start address and length of the partition based on the size of the files to be burnt. Make sure the size of the partition is greater than that of the files to be burnt and the partition addresses of the files to be burnt do not overlap.
![en-us_image_0000001268653461](figures/en-us_image_0000001268653461.png)
3. Follow the same procedure to modify the information about the **parameter**, **uboot**, **boot_linuxv, **system**, **vendor**, and **userdata** files.
7. When you finish modifying, click **Save** on the top.
8. Click **Open** to open the project file. Click ![en-us_image_0000001239221905](figures/en-us_image_0000001239221905.png) to open DevEco Device Tool. Then, choose **PROJECT TASKS** > **hh_scdy200** > **Upload** to start burning.
![en-us_image_0000001194821710](figures/en-us_image_0000001194821710.png)
9. Wait until the burning is complete. If the following message is displayed, the burning is successful.
![en-us_image_0000001194984912](figures/en-us_image_0000001194984912.png)
# Writing a Hello World Program
The following exemplifies how to run the first program on the development board. The created program outputs the message "Hello World!" .
## Example Directory
The complete code directory is as follows:
```
applications/sample/hello
│ │── BUILD.gn
│ │── include
│ │ └── helloworld.h
│ │── src
│ │ └── helloworld.c
│ └── bundle.json
build
└── subsystem_config.json
productdefine/common
└── products
└── rk3568.json
```
## How to Develop
Perform the steps below in the source code directory:
1. Create a directory and write the service code.
Create the **applications/sample/hello/src/helloworld.c** directory and file whose code is shown in the following example. You can customize the content to be printed. For example, you can change **World** to **OH**. Declare the string printing function **HelloPrint** in the **helloworld.h** file. You can use either C or C++ to develop a program.
```
#include <stdio.h>
#include "helloworld.h"
int main(int argc, char **argv)
{
HelloPrint();
return 0;
}
void HelloPrint()
{
printf("\n\n");
printf("\n\t\tHello World!\n");
printf("\n\n");
}
```
Add the header file **applications/sample/hello/include/helloworld.h**. The sample code is as follows:
```
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif
void HelloPrint();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif // HELLOWORLD_H
```
2. Create a build file.
1. Create the **applications/sample/hello/BUILD.gn** file. The file content is as follows:
```
import("//build/ohos.gni") # Import the build template.
ohos_executable("helloworld") {# Executable module.
sources = [ # Source code of the module.
"src/helloworld.c"
]
include_dirs = [ # Directory of header file on which the module depends.
"include"
]
cflags = []
cflags_c = []
cflags_cc = []
ldflags = []
configs = []
deps =[] # Internal dependencies of a component.
part_name = "hello" # Component name. This parameter is mandatory.
install_enable = true # Whether to install the software by default. This parameter is optional. By default, the software is not installed.
}
```
2. Create the **applications/sample/hello/bundle.json** file and add the description of the **sample** component. The content is as follows:
```
{
"name": "@ohos/hello",
"description": "Hello world example.",
"version": "3.1",
"license": "Apache License 2.0",
"publishAs": "code-segment",
"segment": {
"destPath": "applications/sample/hello"
},
"dirs": {},
"scripts": {},
"component": {
"name": "hello",
"subsystem": "sample",
"syscap": [],
"features": [],
"adapted_system_type": [ "mini", "small", "standard" ],
"rom": "10KB",
"ram": "10KB",
"deps": {
"components": [],
"third_party": []
},
"build": {
"sub_component": [
"//applications/sample/hello:helloworld"
],
"inner_kits": [],
"test": []
}
}
}
```
The **bundle.json** file consists of two parts. The first part describes the information about the subsystem to which the component belongs, and the second part defines the component building configuration. When adding a part, you need to specify the **sub_component** contained in the part. If there are interfaces provided for other components, describe them in **inner_kits**. If there are test cases, describe them in **test**.
3. Modify the subsystem configuration file.
Add the configuration of the new subsystem to the **build/subsystem_config.json** file.
```
"sample": {
"path": "applications/sample/hello",
"name": "sample"
},
```
4. Modify the product configuration file.
In the **productdefine/common/products/rk3568.json** file, add the **hello** part after the existing part.
```
"usb:usb_manager_native":{},
"applications:prebuilt_hap":{},
"sample:hello":{},
"wpa_supplicant-2.9:wpa_supplicant-2.9":{},
```
# Running
## Starting the System
After the image is burnt and the development board is restarted, the system automatically starts. If the following page is displayed on the screen of the development board, the system is running properly.
**Figure 1** System startup effect
![en-us_image_0000001226602406](figures/en-us_image_0000001226602406.jpg)
## Running a Hello World Program
1. When the system is running, start the serial port tool (for example, PuTTY), set the baud rate to **1500000**, and connect to the device.
![en-us_image_0000001226922310](figures/en-us_image_0000001226922310.png)
2. Enable the serial port, enter the **helloworld** command in any directory (for example, the root directory of the device) and press **Enter**. If the message "Hello World!" is displayed, the program runs successfully.
![en-us_image_0000001271202465](figures/en-us_image_0000001271202465.png)
# RK3568 Development Board
- **[Writing a Hello World Program](quickstart-standard-running-rk3568-create.md)**
- **[Building](quickstart-standard-running-rk3568-build.md)**
- **[Burning](quickstart-standard-running-rk3568-burning.md)**
- **[Running](quickstart-standard-running-rk3568-running.md)**
# Running an Image<a name="EN-US_TOPIC_0000001142160948"></a> # Running a Hello World Program
## Running an Image<a name="section153991115191314"></a>
After the image burning is complete, perform the following steps to run the system:
>![](../public_sys-resources/icon-note.gif) **NOTE:** - **[Hi3516 Development Board](quickstart-standard-running-hi3516.md)**
>This operation procedure is required only if this is the first time you burn an image for the standard system.
1. In DevEco Device Tool, click **Monitor** to open the serial port tool.
![](figures/open-the-serial-port-tool.png)
2. Restart the development board. Before the autoboot countdown ends, press any key to enter the system.
![](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 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 0x82000000 0x800 0x4800; bootm 0x82000000'
```
![](figures/setenv-bootargs.png)
4. Save the parameter settings.
```
save
```
![](figures/save-the-parameter-settings.png)
5. Restart the development board to start the system.
```
reset
```
![](figures/start-the-system.png)
## 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).
- **[RK3568 Development Board](quickstart-standard-running-rk3568.md)**
# Obtaining Source Code<a name="EN-US_TOPIC_0000001188523654"></a>
### Prerequisites<a name="section1787412417496"></a>
1. Register your account with Gitee.
2. Register an SSH public key for access to Gitee.
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"
git config --global user.email "your-email-address"
git config --global credential.helper store
```
4. Run the following commands to install the **repo** tool:
```
curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 -o /usr/local/bin/repo # If you do not have the access permission to this directory, download the tool to any other accessible directory and configure the directory to the environment variable.
chmod a+x /usr/local/bin/repo
pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests
```
### How to Obtain<a name="section1715918316415"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE**<br/>
>Download the master code if you want to get quick access to the latest features for your development. Download the release code, which is more stable, if you want to develop commercial functionalities.
- **Obtaining OpenHarmony master 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'
```
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'
```
- **Obtaining OpenHarmony release code**
For details about how to obtain the source code of an OpenHarmony release, see the [Release-Notes](../get-code/../../release-notes/Readme.md).
# Standard System<a name="EN-US_TOPIC_0000001111221726"></a> # Getting Started with Standard System
- **[Introduction](quickstart-standard-overview.md)**
- **[Setting Up a Windows Development Environment](quickstart-standard-windows-environment.md)**
- **[Setting Up a Ubuntu Development Environment in Docker Mode](quickstart-standard-docker-environment.md)**
- **[Setting Up a Ubuntu Development Environment Using the Installation Package](quickstart-standard-package-environment.md)**
- **[Burning Images](quickstart-standard-burn.md)**
- **[Running an Image](quickstart-standard-running.md)**
- **[FAQs](quickstart-standard-faqs.md)**
- **[Getting Started with Standard System (IDE Mode)](quickstart-standard-ide-directory.md)**
- **[Getting Started with Standard System (Installation Package Mode)](quickstart-standard-package-directory.md)**
# Getting Started<a name="EN-US_TOPIC_0000001157479389"></a> # Getting Started
- **[Mini and Small Systems](quickstart-lite.md)**
- **[Standard System](quickstart-standard.md)**
- **[Getting Started with Mini and Small Systems](quickstart-lite.md)**
- **[Getting Started with Standard System](quickstart-standard.md)**
...@@ -67,9 +67,10 @@ ...@@ -67,9 +67,10 @@
- [Development Guidelines](development-guidelines.md) - [Development Guidelines](development-guidelines.md)
- [Security](subsys-security.md) - [Security](subsys-security.md)
- [Overview](subsys-security-overview.md) - [Overview](subsys-security-overview.md)
- [Development Guidelines on Application Signature Verification](subsys-security-sigverify.md) - [Development on Application Signature Verification](subsys-security-sigverify.md)
- [Development Guidelines on Application Permission Management](subsys-security-rightmanagement.md) - [Development on Application Permission Management](subsys-security-rightmanagement.md)
- [Development Guidelines on IPC Authentication](subsys-security-communicationverify.md) - [Development on IPC Authentication](subsys-security-communicationverify.md)
- [Development on Device Security Level Management](subsys-security-devicesecuritylevel.md)
- [Startup](subsys-boot.md) - [Startup](subsys-boot.md)
- [Startup](subsys-boot-overview.md) - [Startup](subsys-boot-overview.md)
- [init Module](subsys-boot-init.md) - [init Module](subsys-boot-init.md)
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
- Development board: Hi3516D V300 - Development board: Hi3516D V300
- Download the source code - [Obtain source code](../get-code/sourcecode-acquire.md).
- [Build the application framework](../../readme/bundle-management.md).
- Build the application framework
...@@ -62,7 +62,7 @@ After being started by the init process, the appspawn process waits for inter-pr ...@@ -62,7 +62,7 @@ After being started by the init process, the appspawn process waits for inter-pr
</tr> </tr>
<tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gidTable</p> <tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gidTable</p>
</td> </td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p187716587310"><a name="p187716587310"></a><a name="p187716587310"></a>Information about the application process group to be started. Its length is specified by **gidCount**. A maximum of 64 process groups are supported. The value must be a positive number.</p> <td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p187716587310"><a name="p187716587310"></a><a name="p187716587310"></a>Information about the application process group to be started. Its length is specified by <strong>gidCount</strong>. A maximum of 64 process groups are supported. The value must be a positive number.</p>
</td> </td>
</tr> </tr>
<tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gidCount</p> <tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gidCount</p>
...@@ -89,8 +89,8 @@ After being started by the init process, the appspawn process waits for inter-pr ...@@ -89,8 +89,8 @@ After being started by the init process, the appspawn process waits for inter-pr
### Available APIs<a name="section56901555914"></a> ### Available APIs<a name="section56901555914"></a>
**Table 2** Available APIs **Table 2** API description
<table><thead align="left"><tr id="row6650142913713"><th class="cellrowborder" valign="top" width="39.489999999999995%" id="mcps1.2.3.1.1"><p id="p17650112914379"><a name="p17650112914379"></a><a name="p17650112914379"></a>Field</p> <table><thead align="left"><tr id="row6650142913713"><th class="cellrowborder" valign="top" width="39.489999999999995%" id="mcps1.2.3.1.1"><p id="p17650112914379"><a name="p17650112914379"></a><a name="p17650112914379"></a>API</p>
</th> </th>
<th class="cellrowborder" valign="top" width="60.51%" id="mcps1.2.3.1.2"><p id="p865032916376"><a name="p865032916376"></a><a name="p865032916376"></a>Description</p> <th class="cellrowborder" valign="top" width="60.51%" id="mcps1.2.3.1.2"><p id="p865032916376"><a name="p865032916376"></a><a name="p865032916376"></a>Description</p>
</th> </th>
......
...@@ -4,11 +4,11 @@ ...@@ -4,11 +4,11 @@
HiLog is the log system of OpenHarmony that provides logging for the system framework, services, and applications to record information on user operations and system running status. HiLog is the log system of OpenHarmony that provides logging for the system framework, services, and applications to record information on user operations and system running status.
This development guide is applicable to Standard-System Devices \(reference memory ≥ 128 MB\). This development guide is applicable to standard-system devices \(reference memory ≥ 128 MB\).
## Available APIs<a name="section6748124155012"></a> ## Available APIs<a name="section6748124155012"></a>
**Table 1** Description of C++ and C APIs **Table 1** List of C++ and C APIs
<a name="table94501354193619"></a> <a name="table94501354193619"></a>
<table><thead align="left"><tr id="row954285483614"><th class="cellrowborder" valign="top" width="18.258174182581744%" id="mcps1.2.4.1.1"><p id="p16542254203611"><a name="p16542254203611"></a><a name="p16542254203611"></a><strong id="b17542185414366"><a name="b17542185414366"></a><a name="b17542185414366"></a>C++</strong></p> <table><thead align="left"><tr id="row954285483614"><th class="cellrowborder" valign="top" width="18.258174182581744%" id="mcps1.2.4.1.1"><p id="p16542254203611"><a name="p16542254203611"></a><a name="p16542254203611"></a><strong id="b17542185414366"><a name="b17542185414366"></a><a name="b17542185414366"></a>C++</strong></p>
......
# Overview<a name="EN-US_TOPIC_0000001058831526"></a> # Overview
The OpenHarmony security subsystem provides security capabilities that make your applications and devices more secure and help you manage permissions. This subsystem has the following modules: The OpenHarmony security subsystem provides security capabilities that make your applications and devices more secure and help you manage permissions. This subsystem has the following modules:
- Application signature verification
To ensure the content integrity of applications, the system controls sources of the applications through application signatures and profiles. For a debugging application, the system uses the signature verification API to check whether the Unique Device Identifier (UDID) of the application matches that of the device, so as to ensure that the application is installed on the right device. - Application signature verification
- Application permission management To ensure the content integrity of applications, the system controls sources of the applications through application signatures and profiles. For a debugging application, the system uses the signature verification API to check whether the Unique Device Identifier (UDID) of the application matches that of the device, so as to ensure that the application is installed on the right device.
Application permissions determine what system resources and capabilities an application can access. During application development, you need to declare the permissions that the application may require in the **profile.json** file. Static permissions need to be registered during application installation, while dynamic permissions usually involve sensitive information and need users' dynamic authorization. - Application permission management
- Trusted device group management Application permissions determine what system resources and capabilities an application can access. During application development, you need to declare the permissions that the application may require in the profile.json file. Static permissions need to be registered during application installation, while dynamic permissions usually involve sensitive information and need users' dynamic authorization.
You can create and query a group of trusted devices that use the same HUAWEI ID or a peer-to-peer group created by scanning a QR code or using OneHop. With this capability, distributed applications can perform trusted authentication between devices and request from the distributed virtual bus for secure sessions between devices. - Inter-process communication (IPC) authentication
- DSLM The caller that attempts to invoke the APIs provided by system services through IPC must be authenticated. The system services registered with Samgr can expose APIs to other processes through IPC, with access policies configured. When other processes attempt to call these APIs, the IPC authentication mechanism will be triggered. If the processes do not have the access permission, the access request will be rejected.
The OpenHarmony Device Security Level Management (DSLM) module manages the security levels of OpenHarmony devices. When different types of user data are hopped or processed in OpenHarmony distributed services, the DSLM APIs can be called to obtain the security levels of related devices for subsequent processing. - DSLM
The Device Security Level Management (DSLM) module is introduced to manage the security levels of OpenHarmony devices. When different types of user data are hopped or processed in OpenHarmony distributed services, the DSLM APIs can be called to obtain the security levels of related devices for subsequent processing.
## Basic Concepts<a name="section175012297491"></a>
Before developing an application that depends on the signature verification component, you should understand the following basic concepts: ## Basic Concepts
- Samgr
System Ability Manager (Samgr) is a module of OpenHarmony for managing system capabilities. For details, see the Application Framework development guidelines.
Before developing an application that depends on the signature verification component, you should understand the following basic concepts:
- BMS - Samgr
Bundle Manager Service (BMS) manages application installation, uninstallation, and data on OpenHarmony.
System Ability Manager (Samgr) is a module of OpenHarmony for managing system capabilities. For details, see the Application Framework development guidelines.
- Profile - BMS
The profile in this document refers to HarmonyAppProvision (profile for short). HarmonyAppProvision is in JSON format. Bundle Manager Service (BMS) manages application installation, uninstallation, and data on OpenHarmony.
- Profile
- Debugging application The profile in this document refers to HarmonyAppProvision, which is in JSON format.
A debugging application is a HarmonyOS Ability Package (HAP) that is signed with a debugging certificate and profile obtained from the application market. - Debug application
A debug application is an OpenHarmony Ability Package (HAP) that is signed with a debug certificate and profile obtained from the application store.
- Released application - Release application
This application refers to a HAP that is signed with a distribution certificate and profile obtained from the application market, but has been released in the application market. A release application is a HAP that is signed with a release certificate and profile obtained from the application store, and formally released in the application store.
- OpenHarmony self-signed application
- OpenHarmony self-signed application A self-signed application is an application that is signed with the signing certificate and profile issued by OpenHarmony's open-source root CA, which is composed of a certificate and a key.
A self-signed application is one that has been signed with the signing certificate and profile issued by OpenHarmony's open-source root CA, which consists of a certificate and a key.
## Constraints
## Constraints<a name="section2029921310472"></a> - Only signatures of the debug, release, and OpenHarmony self-signed applications can be verified.
- Only signatures of debugging, released, and OpenHarmony self-signed applications can be verified. - To verify the signature of a debug application, the UDID of the device on which the debug application is installed must be in the UDID list contained in the profile.
- To verify the signature of a debugging application, the UDID of the device on which the debugging application is installed must be in the UDID list contained in the profile.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- **[Overview](subsys-security-overview.md)** - **[Overview](subsys-security-overview.md)**
- **[Development on Application Signature Verification] (subsys-security-sigverify.md)** - **[Development on Application Signature Verification](subsys-security-sigverify.md)**
- **[Development on Application Permission Management](subsys-security-rightmanagement.md)** - **[Development on Application Permission Management](subsys-security-rightmanagement.md)**
......
# USB Usage Example<a name="EN-US_TOPIC_0000001092792986"></a> # USB Usage Demo<a name="EN-US_TOPIC_0000001092792986"></a>
``` ```
...@@ -183,5 +183,3 @@ int main(int argc, char **argv) ...@@ -183,5 +183,3 @@ int main(int argc, char **argv)
return 0; return 0;
} }
``` ```
# USB Usage Guidelines<a name="EN-US_TOPIC_0000001077367159"></a> # USB Usage Guidelines<a name="EN-US_TOPIC_0000001077367159"></a>
The following procedure uses bulk transfer as an example. The following procedure uses bulk transfer as an example.
## Procedure<a name="section18816105182315"></a> ## Procedure<a name="section18816105182315"></a>
...@@ -42,7 +43,10 @@ ret = g_usbClient.ClaimInterface(pip, interface, true); ...@@ -42,7 +43,10 @@ ret = g_usbClient.ClaimInterface(pip, interface, true);
``` ```
srvClient.BulkTransfer(pipe, endpoint, vdata, timeout); srvClient.BulkTransfer(pipe, endpoint, vdata, timeout);
``` ```
**pipe** indicates the pipe for data transfer after the USB device is opened. **endpoint** indicates the endpoint for data transfer on the USB device. **vdata** indicates the binary data block to be transferred or read. **timeout** indicates the timeout duration of data transfer. - **pipe** indicates the pipe for data transfer of the USB device opened.
- **endpoint** indicates the endpoint for data transfer on the USB device.
- **vdata** indicates the binary data block to be transferred or read.
- **timeout** indicates the timeout duration of data transfer.
7. Close the USB device. 7. Close the USB device.
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
## Introduction<a name="section465982318513"></a> ## Introduction<a name="section465982318513"></a>
The X test suite \(XTS\) subsystem contains a set of OpenHarmony certification test suites, including the currently supported application compatibility test suite \(ACTS\) and the device compatibility test suite \(DCTS\) that will be supported in the future. The X test suite \(XTS\) subsystem contains a set of OpenHarmony compatibility test suites, including the currently supported application compatibility test suite \(ACTS\) and the device compatibility test suite \(DCTS\) that will be supported in the future.
This subsystem contains the ACTS and **tools** software package. This subsystem contains the ACTS and **tools** software package.
...@@ -690,7 +690,7 @@ Install Python 3.7 or a later version on a Windows environment and ensure that t ...@@ -690,7 +690,7 @@ Install Python 3.7 or a later version on a Windows environment and ensure that t
Wait until the test case is complete. Wait until the test case is complete.
1. View test reports. 3. View test reports.
Go to **acts\\reports\\**, obtain the current execution record, and open **summary\_report.html** to view the test report. Go to **acts\\reports\\**, obtain the current execution record, and open **summary\_report.html** to view the test report.
......
...@@ -384,10 +384,10 @@ ...@@ -384,10 +384,10 @@
- [HiSysEvent Query](subsystems/subsys-dfx-hisysevent-query.md) - [HiSysEvent Query](subsystems/subsys-dfx-hisysevent-query.md)
- [HiSysEvent Tool Usage](subsystems/subsys-dfx-hisysevent-tool.md) - [HiSysEvent Tool Usage](subsystems/subsys-dfx-hisysevent-tool.md)
- Featured Topics - Featured Topics
- HPM Bundle - HPM Part
- [HPM Part Overview](bundles/hpm-part-about.md) - [HPM Part Overview](hpm-part/hpm-part-about.md)
- [HPM Part Development](bundles/hpm-part-development.md) - [HPM Part Development](hpm-part/hpm-part-development.md)
- [HPM Part Reference](bundles/hpm-part-reference.md) - [HPM Part Reference](hpm-part/hpm-part-reference.md)
- Device Development Examples - Device Development Examples
- [Mini- and Small-System Devices](guide/device-lite.md) - [Mini- and Small-System Devices](guide/device-lite.md)
- [WLAN-connected Products](guide/device-wlan.md) - [WLAN-connected Products](guide/device-wlan.md)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册